From 1f038048612e01d0ada6deb9ff2a056cb8d13702 Mon Sep 17 00:00:00 2001 From: Eleanor Eng Date: Mon, 11 Mar 2019 17:32:49 -0400 Subject: some changes --- src/client/views/nodes/FormattedTextBox.tsx | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) (limited to 'src/client/views/nodes/FormattedTextBox.tsx') diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index 8b3deeb8b..baedf0852 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -119,17 +119,18 @@ export class FormattedTextBox extends React.Component { specificContextMenu = (e: React.MouseEvent): void => { ContextMenu.Instance.addItem({ description: "Text Capability", event: this.textCapability }); - // ContextMenu.Instance.addItem({ - // description: "Submenu", - // items: [ - // { - // description: "item 1", event: - // }, - // { - // description: "item 2", event: - // } - // ] - // }) + ContextMenu.Instance.addItem({ + description: "Submenu", subitems: + [{ description: "Sub 1", event: this.textCapability }] + // [{ description: "Sub 2", event: this.textCapability }] + // { + // description: "item 1", event: + // }, + // { + // description: "item 2", event: + // } + // ] + }) // e.stopPropagation() } -- cgit v1.2.3-70-g09d2 From 9351426356e06a5c6a7777b1edd118273e29072e Mon Sep 17 00:00:00 2001 From: Eleanor Eng Date: Tue, 12 Mar 2019 17:45:57 -0400 Subject: working submenu; dimensions use vw, vh --- package-lock.json | 236 +++++++++++++++------------- src/client/views/ContextMenu.scss | 1 - src/client/views/ContextMenu.tsx | 6 +- src/client/views/nodes/FormattedTextBox.tsx | 21 +-- 4 files changed, 140 insertions(+), 124 deletions(-) (limited to 'src/client/views/nodes/FormattedTextBox.tsx') diff --git a/package-lock.json b/package-lock.json index 75c02628e..8c9bf9c0a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1138,7 +1138,7 @@ }, "util": { "version": "0.10.3", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "resolved": "http://registry.npmjs.org/util/-/util-0.10.3.tgz", "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", "dev": true, "requires": { @@ -1655,7 +1655,7 @@ }, "browserify-aes": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "resolved": "http://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", "dev": true, "requires": { @@ -1692,7 +1692,7 @@ }, "browserify-rsa": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", + "resolved": "http://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", "dev": true, "requires": { @@ -1731,7 +1731,7 @@ }, "buffer": { "version": "4.9.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", + "resolved": "http://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", "dev": true, "requires": { @@ -1852,7 +1852,7 @@ }, "camelcase-keys": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", + "resolved": "http://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", "requires": { "camelcase": "^2.0.0", @@ -2282,7 +2282,7 @@ }, "content-disposition": { "version": "0.5.2", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", + "resolved": "http://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=" }, "content-type": { @@ -2401,7 +2401,7 @@ }, "create-hash": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "resolved": "http://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", "dev": true, "requires": { @@ -2414,7 +2414,7 @@ }, "create-hmac": { "version": "1.1.7", - "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "resolved": "http://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", "dev": true, "requires": { @@ -2540,7 +2540,7 @@ }, "d": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", + "resolved": "http://registry.npmjs.org/d/-/d-1.0.0.tgz", "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", "dev": true, "requires": { @@ -2763,7 +2763,7 @@ }, "diffie-hellman": { "version": "5.0.3", - "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "resolved": "http://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", "dev": true, "requires": { @@ -3306,7 +3306,7 @@ "dependencies": { "array-flatten": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "resolved": "http://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" }, "statuses": { @@ -3500,7 +3500,7 @@ }, "finalhandler": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", + "resolved": "http://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==", "requires": { "debug": "2.6.9", @@ -3574,14 +3574,18 @@ }, "dependencies": { "readable-stream": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.1.1.tgz", - "integrity": "sha512-DkN66hPyqDhnIQ6Jcsvx9bFjhw214O4poMBcIMgPVpQvNy9a0e0Uhg5SqySyDKAmUlwt8LonTBz1ezOnM8pUdA==", + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" } } } @@ -3703,24 +3707,24 @@ "dependencies": { "abbrev": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "resolved": false, "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", "optional": true }, "ansi-regex": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "resolved": false, "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" }, "aproba": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "resolved": false, "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", "optional": true }, "are-we-there-yet": { "version": "1.1.5", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", + "resolved": false, "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", "optional": true, "requires": { @@ -3730,12 +3734,12 @@ }, "balanced-match": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "resolved": false, "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" }, "brace-expansion": { "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "resolved": false, "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "requires": { "balanced-match": "^1.0.0", @@ -3744,34 +3748,34 @@ }, "chownr": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.1.tgz", + "resolved": false, "integrity": "sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g==", "optional": true }, "code-point-at": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "resolved": false, "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" }, "concat-map": { "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "resolved": false, "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, "console-control-strings": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "resolved": false, "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" }, "core-util-is": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "resolved": false, "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", "optional": true }, "debug": { "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "resolved": false, "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "optional": true, "requires": { @@ -3780,25 +3784,25 @@ }, "deep-extend": { "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "resolved": false, "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", "optional": true }, "delegates": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "resolved": false, "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", "optional": true }, "detect-libc": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "resolved": false, "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", "optional": true }, "fs-minipass": { "version": "1.2.5", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.5.tgz", + "resolved": false, "integrity": "sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ==", "optional": true, "requires": { @@ -3807,13 +3811,13 @@ }, "fs.realpath": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "resolved": false, "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "optional": true }, "gauge": { "version": "2.7.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "resolved": false, "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", "optional": true, "requires": { @@ -3829,7 +3833,7 @@ }, "glob": { "version": "7.1.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "resolved": false, "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", "optional": true, "requires": { @@ -3843,13 +3847,13 @@ }, "has-unicode": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "resolved": false, "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", "optional": true }, "iconv-lite": { "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "resolved": false, "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "optional": true, "requires": { @@ -3858,7 +3862,7 @@ }, "ignore-walk": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.1.tgz", + "resolved": false, "integrity": "sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ==", "optional": true, "requires": { @@ -3867,7 +3871,7 @@ }, "inflight": { "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "resolved": false, "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "optional": true, "requires": { @@ -3877,18 +3881,18 @@ }, "inherits": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "resolved": false, "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" }, "ini": { "version": "1.3.5", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "resolved": false, "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", "optional": true }, "is-fullwidth-code-point": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "resolved": false, "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "requires": { "number-is-nan": "^1.0.0" @@ -3896,13 +3900,13 @@ }, "isarray": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "resolved": false, "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "optional": true }, "minimatch": { "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "resolved": false, "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "requires": { "brace-expansion": "^1.1.7" @@ -3910,12 +3914,12 @@ }, "minimist": { "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "resolved": false, "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" }, "minipass": { "version": "2.3.5", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.3.5.tgz", + "resolved": false, "integrity": "sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA==", "requires": { "safe-buffer": "^5.1.2", @@ -3924,7 +3928,7 @@ }, "minizlib": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.2.1.tgz", + "resolved": false, "integrity": "sha512-7+4oTUOWKg7AuL3vloEWekXY2/D20cevzsrNT2kGWm+39J9hGTCBv8VI5Pm5lXZ/o3/mdR4f8rflAPhnQb8mPA==", "optional": true, "requires": { @@ -3933,7 +3937,7 @@ }, "mkdirp": { "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "resolved": false, "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", "requires": { "minimist": "0.0.8" @@ -3941,13 +3945,13 @@ }, "ms": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "resolved": false, "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "optional": true }, "needle": { "version": "2.2.4", - "resolved": "https://registry.npmjs.org/needle/-/needle-2.2.4.tgz", + "resolved": false, "integrity": "sha512-HyoqEb4wr/rsoaIDfTH2aVL9nWtQqba2/HvMv+++m8u0dz808MaagKILxtfeSN7QU7nvbQ79zk3vYOJp9zsNEA==", "optional": true, "requires": { @@ -3958,7 +3962,7 @@ }, "node-pre-gyp": { "version": "0.10.3", - "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.10.3.tgz", + "resolved": false, "integrity": "sha512-d1xFs+C/IPS8Id0qPTZ4bUT8wWryfR/OzzAFxweG+uLN85oPzyo2Iw6bVlLQ/JOdgNonXLCoRyqDzDWq4iw72A==", "optional": true, "requires": { @@ -3976,7 +3980,7 @@ }, "nopt": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz", + "resolved": false, "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", "optional": true, "requires": { @@ -3986,13 +3990,13 @@ }, "npm-bundled": { "version": "1.0.5", - "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.0.5.tgz", + "resolved": false, "integrity": "sha512-m/e6jgWu8/v5niCUKQi9qQl8QdeEduFA96xHDDzFGqly0OOjI7c+60KM/2sppfnUU9JJagf+zs+yGhqSOFj71g==", "optional": true }, "npm-packlist": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.2.0.tgz", + "resolved": false, "integrity": "sha512-7Mni4Z8Xkx0/oegoqlcao/JpPCPEMtUvsmB0q7mgvlMinykJLSRTYuFqoQLYgGY8biuxIeiHO+QNJKbCfljewQ==", "optional": true, "requires": { @@ -4002,7 +4006,7 @@ }, "npmlog": { "version": "4.1.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "resolved": false, "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", "optional": true, "requires": { @@ -4014,18 +4018,18 @@ }, "number-is-nan": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "resolved": false, "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" }, "object-assign": { "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "resolved": false, "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", "optional": true }, "once": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "resolved": false, "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "requires": { "wrappy": "1" @@ -4033,19 +4037,19 @@ }, "os-homedir": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "resolved": false, "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", "optional": true }, "os-tmpdir": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "resolved": false, "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "optional": true }, "osenv": { "version": "0.1.5", - "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", + "resolved": false, "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", "optional": true, "requires": { @@ -4055,19 +4059,19 @@ }, "path-is-absolute": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "resolved": false, "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "optional": true }, "process-nextick-args": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "resolved": false, "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", "optional": true }, "rc": { "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "resolved": false, "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", "optional": true, "requires": { @@ -4079,7 +4083,7 @@ "dependencies": { "minimist": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "resolved": false, "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "optional": true } @@ -4087,7 +4091,7 @@ }, "readable-stream": { "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "resolved": false, "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "optional": true, "requires": { @@ -4102,7 +4106,7 @@ }, "rimraf": { "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "resolved": false, "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", "optional": true, "requires": { @@ -4111,42 +4115,42 @@ }, "safe-buffer": { "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "resolved": false, "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, "safer-buffer": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "resolved": false, "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "optional": true }, "sax": { "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "resolved": false, "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", "optional": true }, "semver": { "version": "5.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", + "resolved": false, "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", "optional": true }, "set-blocking": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "resolved": false, "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "optional": true }, "signal-exit": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "resolved": false, "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", "optional": true }, "string-width": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "resolved": false, "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "requires": { "code-point-at": "^1.0.0", @@ -4156,7 +4160,7 @@ }, "string_decoder": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "resolved": false, "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "optional": true, "requires": { @@ -4165,7 +4169,7 @@ }, "strip-ansi": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "resolved": false, "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "requires": { "ansi-regex": "^2.0.0" @@ -4173,13 +4177,13 @@ }, "strip-json-comments": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "resolved": false, "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", "optional": true }, "tar": { "version": "4.4.8", - "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.8.tgz", + "resolved": false, "integrity": "sha512-LzHF64s5chPQQS0IYBn9IN5h3i98c12bo4NCO7e0sGM2llXQ3p2FGC5sdENN4cTW48O915Sh+x+EXx7XW96xYQ==", "optional": true, "requires": { @@ -4194,13 +4198,13 @@ }, "util-deprecate": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "resolved": false, "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "optional": true }, "wide-align": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "resolved": false, "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", "optional": true, "requires": { @@ -4209,12 +4213,12 @@ }, "wrappy": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "resolved": false, "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "yallist": { "version": "3.0.3", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", + "resolved": false, "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==" } } @@ -4640,7 +4644,7 @@ }, "http-errors": { "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "resolved": "http://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", "requires": { "depd": "~1.1.2", @@ -4943,7 +4947,7 @@ }, "is-accessor-descriptor": { "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "resolved": "http://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", "requires": { "kind-of": "^3.0.2" @@ -4987,7 +4991,7 @@ }, "is-data-descriptor": { "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "resolved": "http://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", "requires": { "kind-of": "^3.0.2" @@ -5466,7 +5470,7 @@ }, "load-json-file": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", "requires": { "graceful-fs": "^4.1.2", @@ -5767,7 +5771,7 @@ }, "media-typer": { "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "resolved": "http://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" }, "mem": { @@ -5799,7 +5803,7 @@ }, "meow": { "version": "3.7.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", + "resolved": "http://registry.npmjs.org/meow/-/meow-3.7.0.tgz", "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", "requires": { "camelcase-keys": "^2.0.0", @@ -5965,7 +5969,7 @@ }, "mkdirp": { "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", "requires": { "minimist": "0.0.8" @@ -6243,7 +6247,7 @@ }, "next-tick": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "resolved": "http://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", "dev": true }, @@ -6302,7 +6306,7 @@ }, "semver": { "version": "5.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "resolved": "http://registry.npmjs.org/semver/-/semver-5.3.0.tgz", "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=" }, "tar": { @@ -9685,12 +9689,12 @@ }, "os-homedir": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "resolved": "http://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" }, "os-tmpdir": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "resolved": "http://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" }, "osenv": { @@ -9856,7 +9860,7 @@ }, "path-browserify": { "version": "0.0.0", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", + "resolved": "http://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=", "dev": true }, @@ -9875,7 +9879,7 @@ }, "path-is-absolute": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "resolved": "http://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" }, "path-is-inside": { @@ -10888,7 +10892,7 @@ }, "readable-stream": { "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "requires": { "core-util-is": "~1.0.0", @@ -11149,7 +11153,7 @@ }, "safe-regex": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "resolved": "http://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", "requires": { "ret": "~0.1.10" @@ -11371,7 +11375,7 @@ }, "sha.js": { "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "resolved": "http://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", "dev": true, "requires": { @@ -11929,11 +11933,31 @@ "requires": { "is-fullwidth-code-point": "^2.0.0", "strip-ansi": "^4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "requires": { + "ansi-regex": "^3.0.0" + } + } } }, "string_decoder": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "requires": { "safe-buffer": "~5.1.0" @@ -11941,7 +11965,7 @@ }, "strip-ansi": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "requires": { "ansi-regex": "^2.0.0" @@ -11957,7 +11981,7 @@ }, "strip-eof": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "resolved": "http://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=" }, "strip-indent": { @@ -12393,7 +12417,7 @@ }, "tty-browserify": { "version": "0.0.0", - "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", + "resolved": "http://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", "dev": true }, @@ -12798,7 +12822,7 @@ }, "vm-browserify": { "version": "0.0.4", - "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", + "resolved": "http://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=", "dev": true, "requires": { @@ -13587,7 +13611,7 @@ }, "wrap-ansi": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "resolved": "http://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", "requires": { "string-width": "^1.0.1", diff --git a/src/client/views/ContextMenu.scss b/src/client/views/ContextMenu.scss index 82e736520..bfd643caf 100644 --- a/src/client/views/ContextMenu.scss +++ b/src/client/views/ContextMenu.scss @@ -12,7 +12,6 @@ z-index: 1000; box-shadow: #AAAAAA .2vw .2vw .4vw; flex-direction: column; - left: 100%; //should make this appear 100% to the right of the parent element (the original context menu) } .contextMenu-item { diff --git a/src/client/views/ContextMenu.tsx b/src/client/views/ContextMenu.tsx index 8a8403c62..ce9023352 100644 --- a/src/client/views/ContextMenu.tsx +++ b/src/client/views/ContextMenu.tsx @@ -9,7 +9,6 @@ export class ContextMenu extends React.Component { static Instance: ContextMenu @observable private _items: Array = [{ description: "test", event: (e: React.MouseEvent) => e.preventDefault() }]; - //need to add a subitems component? @observable private _pageX: number = 0; @observable private _pageY: number = 0; @observable private _display: string = "none"; @@ -37,6 +36,7 @@ export class ContextMenu extends React.Component { if (this._items.indexOf(item) === -1) { this._items.push(item); } + console.log(`After adding, there are ${this._items.length} items`); } getItems() { @@ -81,6 +81,4 @@ export class ContextMenu extends React.Component { onChange = (e: React.ChangeEvent) => { this._searchString = e.target.value; } -} - -// \ No newline at end of file +} \ No newline at end of file diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index 411b43cd5..dfc7e9096 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -122,22 +122,17 @@ export class FormattedTextBox extends React.Component { textCapability = (e: React.MouseEvent): void => { } + @action specificContextMenu = (e: React.MouseEvent): void => { ContextMenu.Instance.addItem({ description: "Text Capability", event: this.textCapability }); ContextMenu.Instance.addItem({ - description: "Submenu", subitems: - [{ description: "Sub 1", event: this.textCapability }] - // [{ description: "Sub 2", event: this.textCapability }] - // { - // description: "item 1", event: - // }, - // { - // description: "item 2", event: - // } - // ] - }) - // e.stopPropagation() - + description: "Submenu", subitems: [ + { description: "Subitem 1", event: this.textCapability }, + { description: "Subitem 2", event: this.textCapability }, + { description: "Subitem 3", event: this.textCapability }, + { description: "Submenu", subitems: [{ description: "Inner Subitem", event: this.textCapability }] } + ] + }); } onPointerWheel = (e: React.WheelEvent): void => { -- cgit v1.2.3-70-g09d2 From 02f0311a868decd92af53d1ffbb6f03bdaa912db Mon Sep 17 00:00:00 2001 From: Eleanor Eng Date: Sat, 16 Mar 2019 16:53:46 -0400 Subject: submenus overlapping --- src/client/views/ContextMenu.scss | 2 +- src/client/views/ContextMenu.tsx | 11 ++++++++++- src/client/views/ContextMenuItem.tsx | 2 +- src/client/views/nodes/FormattedTextBox.tsx | 2 +- 4 files changed, 13 insertions(+), 4 deletions(-) (limited to 'src/client/views/nodes/FormattedTextBox.tsx') diff --git a/src/client/views/ContextMenu.scss b/src/client/views/ContextMenu.scss index bcf856d48..265cdefca 100644 --- a/src/client/views/ContextMenu.scss +++ b/src/client/views/ContextMenu.scss @@ -16,7 +16,7 @@ .contextMenu-item { width: 10vw; //10vw - height: auto; //4vh + height: 2vh; background: #DDDDDD; display: flex; justify-content: left; diff --git a/src/client/views/ContextMenu.tsx b/src/client/views/ContextMenu.tsx index 31c165373..73bad477b 100644 --- a/src/client/views/ContextMenu.tsx +++ b/src/client/views/ContextMenu.tsx @@ -3,6 +3,11 @@ import { ContextMenuItem, ContextMenuProps } from "./ContextMenuItem"; import { observable, action } from "mobx"; import { observer } from "mobx-react" import "./ContextMenu.scss" +import { library } from '@fortawesome/fontawesome-svg-core'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { faSearch } from '@fortawesome/free-solid-svg-icons'; + +library.add(faSearch); @observer export class ContextMenu extends React.Component { @@ -67,7 +72,11 @@ export class ContextMenu extends React.Component { render() { return (
- +
+ + {/* */} + +
{this._items.filter(prop => { return prop.description.toLowerCase().indexOf(this._searchString.toLowerCase()) !== -1; }).map(prop => { diff --git a/src/client/views/ContextMenuItem.tsx b/src/client/views/ContextMenuItem.tsx index 67bbc3082..6bd370152 100644 --- a/src/client/views/ContextMenuItem.tsx +++ b/src/client/views/ContextMenuItem.tsx @@ -38,7 +38,7 @@ export class ContextMenuItem extends React.Component { else { let submenu = null; if (this.overItem) { - submenu = (
+ submenu = (
{this._items.map(prop => { return })} diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index dfc7e9096..e402392a7 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -126,7 +126,7 @@ export class FormattedTextBox extends React.Component { specificContextMenu = (e: React.MouseEvent): void => { ContextMenu.Instance.addItem({ description: "Text Capability", event: this.textCapability }); ContextMenu.Instance.addItem({ - description: "Submenu", subitems: [ + description: "Sub", subitems: [ { description: "Subitem 1", event: this.textCapability }, { description: "Subitem 2", event: this.textCapability }, { description: "Subitem 3", event: this.textCapability }, -- cgit v1.2.3-70-g09d2 From 7db0071a1f1232112597176b0b077e6b7e37679d Mon Sep 17 00:00:00 2001 From: Eleanor Eng Date: Mon, 18 Mar 2019 19:00:13 -0400 Subject: Added icons --- src/client/views/ContextMenu.scss | 12 +++++--- src/client/views/ContextMenu.tsx | 14 +++++---- src/client/views/ContextMenuItem.tsx | 11 ++++++-- src/client/views/collections/CollectionPDFView.tsx | 2 +- src/client/views/collections/CollectionView.tsx | 19 ++++++++++--- src/client/views/nodes/DocumentView.tsx | 33 ++++++++++++++++------ src/client/views/nodes/FormattedTextBox.tsx | 18 +++++++----- src/client/views/nodes/ImageBox.tsx | 2 +- 8 files changed, 77 insertions(+), 34 deletions(-) (limited to 'src/client/views/nodes/FormattedTextBox.tsx') diff --git a/src/client/views/ContextMenu.scss b/src/client/views/ContextMenu.scss index 43e5033fd..5c40c3c43 100644 --- a/src/client/views/ContextMenu.scss +++ b/src/client/views/ContextMenu.scss @@ -15,10 +15,9 @@ } .contextMenu-item { - width: 10vw; //10vw - height: 2vh; - background: #DDDDDD; - display: flex; + width: 11vw; //10vw + height: 2.5vh; //2vh + background: #DDDDDD; // display: flex; justify-content: left; align-items: center; -webkit-touch-callout: none; @@ -46,4 +45,9 @@ font-size: 1.5vw; text-align: left; width: 8vw; + display: inline; //need this? +} + +.icon-background { + background-color: #DDDDDD; } \ No newline at end of file diff --git a/src/client/views/ContextMenu.tsx b/src/client/views/ContextMenu.tsx index 2396ce762..39ccb55b0 100644 --- a/src/client/views/ContextMenu.tsx +++ b/src/client/views/ContextMenu.tsx @@ -13,7 +13,7 @@ library.add(faSearch); export class ContextMenu extends React.Component { static Instance: ContextMenu - @observable private _items: Array = [{ description: "test", event: (e: React.MouseEvent) => e.preventDefault() }]; + @observable private _items: Array = [{ description: "test", event: (e: React.MouseEvent) => e.preventDefault(), icon: "smile" }]; @observable private _pageX: number = 0; @observable private _pageY: number = 0; @observable private _display: string = "none"; @@ -72,11 +72,13 @@ export class ContextMenu extends React.Component { render() { return (
-
- {/* */} - - -
+ + + + + + + {this._items.filter(prop => { return prop.description.toLowerCase().indexOf(this._searchString.toLowerCase()) !== -1; }).map(prop => { diff --git a/src/client/views/ContextMenuItem.tsx b/src/client/views/ContextMenuItem.tsx index 6b17c5c19..80d9ff6a5 100644 --- a/src/client/views/ContextMenuItem.tsx +++ b/src/client/views/ContextMenuItem.tsx @@ -1,10 +1,13 @@ import React = require("react"); import { observable, action } from "mobx"; import { observer } from "mobx-react"; +import { library, IconProp } from '@fortawesome/fontawesome-svg-core'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; export interface OriginalMenuProps { description: string; event: (e: React.MouseEvent) => void; + icon: IconProp; //maybe should be optional (icon?) } export interface SubmenuProps { @@ -17,8 +20,6 @@ export type ContextMenuProps = OriginalMenuProps | SubmenuProps; @observer export class ContextMenuItem extends React.Component { @observable private _items: Array = []; - @observable private _pageX: number = 0; - @observable private _pageY: number = 0; @observable private overItem = false; constructor(props: ContextMenuProps) { @@ -32,13 +33,17 @@ export class ContextMenuItem extends React.Component { if ("event" in this.props) { return (
+ + + +
{this.props.description}
) } else { let submenu = null; if (this.overItem) { - submenu = (
+ submenu = (
{this._items.map(prop => { return })} diff --git a/src/client/views/collections/CollectionPDFView.tsx b/src/client/views/collections/CollectionPDFView.tsx index f22c07060..bcb1cd2f7 100644 --- a/src/client/views/collections/CollectionPDFView.tsx +++ b/src/client/views/collections/CollectionPDFView.tsx @@ -41,7 +41,7 @@ export class CollectionPDFView extends React.Component { specificContextMenu = (e: React.MouseEvent): void => { if (!e.isPropagationStopped() && this.props.Document.Id != "mainDoc") { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7 - ContextMenu.Instance.addItem({ description: "PDFOptions", event: () => { } }); + ContextMenu.Instance.addItem({ description: "PDFOptions", event: () => { }, icon: "file-pdf" }); } } diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 548a51bf1..b76426429 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -13,6 +13,17 @@ import { CollectionSchemaView } from "./CollectionSchemaView"; import { CollectionViewProps } from "./CollectionViewBase"; import { CollectionTreeView } from "./CollectionTreeView"; import { Field, FieldId } from "../../../fields/Field"; +import { library } from '@fortawesome/fontawesome-svg-core'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { faTh } from '@fortawesome/free-solid-svg-icons'; +import { faTree } from '@fortawesome/free-solid-svg-icons'; +import { faSquare } from '@fortawesome/free-solid-svg-icons'; +import { faProjectDiagram } from '@fortawesome/free-solid-svg-icons'; + +library.add(faTh); +library.add(faTree); +library.add(faSquare); +library.add(faProjectDiagram); export enum CollectionViewType { Invalid, @@ -96,10 +107,10 @@ export class CollectionView extends React.Component { specificContextMenu = (e: React.MouseEvent): void => { if (!e.isPropagationStopped() && this.props.Document.Id != "mainDoc") { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7 - ContextMenu.Instance.addItem({ description: "Freeform", event: () => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Freeform) }) - ContextMenu.Instance.addItem({ description: "Schema", event: () => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Schema) }) - ContextMenu.Instance.addItem({ description: "Treeview", event: () => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Tree) }) - ContextMenu.Instance.addItem({ description: "Docking", event: () => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Docking) }) + ContextMenu.Instance.addItem({ description: "Freeform", event: () => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Freeform), icon: "project-diagram" }) + ContextMenu.Instance.addItem({ description: "Schema", event: () => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Schema), icon: "th" }) + ContextMenu.Instance.addItem({ description: "Treeview", event: () => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Tree), icon: "tree" }) + ContextMenu.Instance.addItem({ description: "Docking", event: () => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Docking), icon: "square" }) } } diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index dc793c16d..53a3aaa18 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -27,6 +27,23 @@ import React = require("react"); import { TextField } from "../../../fields/TextField"; import { DocumentManager } from "../../util/DocumentManager"; const JsxParser = require('react-jsx-parser').default; //TODO Why does this need to be imported like this? +import { library } from '@fortawesome/fontawesome-svg-core'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { faTrash } from '@fortawesome/free-solid-svg-icons'; +import { faExpandArrowsAlt } from '@fortawesome/free-solid-svg-icons'; +import { faCompressArrowsAlt } from '@fortawesome/free-solid-svg-icons'; +import { faLayerGroup } from '@fortawesome/free-solid-svg-icons'; +import { faAlignCenter } from '@fortawesome/free-solid-svg-icons'; +import { faCaretSquareRight } from '@fortawesome/free-solid-svg-icons'; +import { faSquare } from '@fortawesome/free-solid-svg-icons'; + +library.add(faTrash); +library.add(faExpandArrowsAlt); +library.add(faCompressArrowsAlt); +library.add(faLayerGroup); +library.add(faAlignCenter); +library.add(faCaretSquareRight); +library.add(faSquare); export interface DocumentViewProps { @@ -212,14 +229,14 @@ export class DocumentView extends React.Component { fullScreenClicked = (e: React.MouseEvent): void => { CollectionDockingView.Instance.OpenFullScreen(this.props.Document); ContextMenu.Instance.clearItems(); - ContextMenu.Instance.addItem({ description: "Close Full Screen", event: this.closeFullScreenClicked }); + ContextMenu.Instance.addItem({ description: "Close Full Screen", event: this.closeFullScreenClicked, icon: "compress-arrows-alt" }); ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15) } closeFullScreenClicked = (e: React.MouseEvent): void => { CollectionDockingView.Instance.CloseFullScreen(); ContextMenu.Instance.clearItems(); - ContextMenu.Instance.addItem({ description: "Full Screen", event: this.fullScreenClicked }) + ContextMenu.Instance.addItem({ description: "Full Screen", event: this.fullScreenClicked, icon: "expand-arrows-alt" }) ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15) } @@ -261,18 +278,18 @@ export class DocumentView extends React.Component { } e.preventDefault() - ContextMenu.Instance.addItem({ description: "Full Screen", event: this.fullScreenClicked }) - ContextMenu.Instance.addItem({ description: "Fields", event: this.fieldsClicked }) - ContextMenu.Instance.addItem({ description: "Center", event: () => this.props.focus(this.props.Document) }) - ContextMenu.Instance.addItem({ description: "Open Right", event: () => CollectionDockingView.Instance.AddRightSplit(this.props.Document) }) - //ContextMenu.Instance.addItem({ description: "Docking", event: () => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Docking) }) + ContextMenu.Instance.addItem({ description: "Full Screen", event: this.fullScreenClicked, icon: "expand-arrows-alt" }) + ContextMenu.Instance.addItem({ description: "Fields", event: this.fieldsClicked, icon: "layer-group" }) + ContextMenu.Instance.addItem({ description: "Center", event: () => this.props.focus(this.props.Document), icon: "align-center" }) + ContextMenu.Instance.addItem({ description: "Open Right", event: () => CollectionDockingView.Instance.AddRightSplit(this.props.Document), icon: "caret-square-right" }) + ContextMenu.Instance.addItem({ description: "Docking", event: () => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Docking), icon: "square" }) ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15) if (!this.topMost) { // DocumentViews should stop propagation of this event e.stopPropagation(); } - ContextMenu.Instance.addItem({ description: "Delete", event: this.deleteClicked }) + ContextMenu.Instance.addItem({ description: "Delete", event: this.deleteClicked, icon: "trash" }) ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15) SelectionManager.SelectDoc(this, e.ctrlKey); } diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index e402392a7..7a8dbddcc 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -14,9 +14,13 @@ import { Plugin } from 'prosemirror-state' import { Decoration, DecorationSet } from 'prosemirror-view' import { TooltipTextMenu } from "../../util/TooltipTextMenu" import { ContextMenu } from "../../views/ContextMenu"; +import { library } from '@fortawesome/fontawesome-svg-core'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { faEdit } from '@fortawesome/free-solid-svg-icons'; +import { faSmile } from '@fortawesome/free-solid-svg-icons'; - - +library.add(faEdit); +library.add(faSmile); // FormattedTextBox: Displays an editable plain text node that maps to a specified Key of a Document // @@ -124,13 +128,13 @@ export class FormattedTextBox extends React.Component { @action specificContextMenu = (e: React.MouseEvent): void => { - ContextMenu.Instance.addItem({ description: "Text Capability", event: this.textCapability }); + ContextMenu.Instance.addItem({ description: "Text Capability", event: this.textCapability, icon: "edit" }); ContextMenu.Instance.addItem({ description: "Sub", subitems: [ - { description: "Subitem 1", event: this.textCapability }, - { description: "Subitem 2", event: this.textCapability }, - { description: "Subitem 3", event: this.textCapability }, - { description: "Submenu", subitems: [{ description: "Inner Subitem", event: this.textCapability }] } + { description: "Subitem 1", event: this.textCapability, icon: "smile" }, + { description: "Subitem 2", event: this.textCapability, icon: "smile" }, + { description: "Subitem 3", event: this.textCapability, icon: "smile" }, + { description: "Submenu", subitems: [{ description: "Inner Subitem", event: this.textCapability, icon: "smile" }] } ] }); } diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index 30910fb1f..62ecea583 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -94,7 +94,7 @@ export class ImageBox extends React.Component { } specificContextMenu = (e: React.MouseEvent): void => { - ContextMenu.Instance.addItem({ description: "Image Capability", event: this.imageCapability }); + ContextMenu.Instance.addItem({ description: "Image Capability", event: this.imageCapability, icon: "smile" }); } render() { -- cgit v1.2.3-70-g09d2 From 19fca408a19c5f7a759ff6c3bfefe27b96ec3563 Mon Sep 17 00:00:00 2001 From: Eleanor Eng Date: Tue, 19 Mar 2019 17:51:25 -0400 Subject: contextmenu --- src/client/views/ContextMenu.scss | 2 +- src/client/views/ContextMenuItem.tsx | 2 +- src/client/views/collections/CollectionView.tsx | 1 - src/client/views/nodes/DocumentView.tsx | 1 - src/client/views/nodes/FormattedTextBox.tsx | 1 - src/client/views/nodes/ImageBox.tsx | 1 - 6 files changed, 2 insertions(+), 6 deletions(-) (limited to 'src/client/views/nodes/FormattedTextBox.tsx') diff --git a/src/client/views/ContextMenu.scss b/src/client/views/ContextMenu.scss index e5d41fcb6..8bc7708f7 100644 --- a/src/client/views/ContextMenu.scss +++ b/src/client/views/ContextMenu.scss @@ -18,7 +18,7 @@ width: 11vw; //10vw height: 2.5vh; //2vh background: #DDDDDD; - display: flex; + display: flex; //comment out to allow search icon to be inline with search text justify-content: left; align-items: center; -webkit-touch-callout: none; diff --git a/src/client/views/ContextMenuItem.tsx b/src/client/views/ContextMenuItem.tsx index 80d9ff6a5..fac7342aa 100644 --- a/src/client/views/ContextMenuItem.tsx +++ b/src/client/views/ContextMenuItem.tsx @@ -1,7 +1,7 @@ import React = require("react"); import { observable, action } from "mobx"; import { observer } from "mobx-react"; -import { library, IconProp } from '@fortawesome/fontawesome-svg-core'; +import { IconProp } from '@fortawesome/fontawesome-svg-core'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; export interface OriginalMenuProps { diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index b76426429..d0e2162b1 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -14,7 +14,6 @@ import { CollectionViewProps } from "./CollectionViewBase"; import { CollectionTreeView } from "./CollectionTreeView"; import { Field, FieldId } from "../../../fields/Field"; import { library } from '@fortawesome/fontawesome-svg-core'; -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faTh } from '@fortawesome/free-solid-svg-icons'; import { faTree } from '@fortawesome/free-solid-svg-icons'; import { faSquare } from '@fortawesome/free-solid-svg-icons'; diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 53a3aaa18..907762837 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -28,7 +28,6 @@ import { TextField } from "../../../fields/TextField"; import { DocumentManager } from "../../util/DocumentManager"; const JsxParser = require('react-jsx-parser').default; //TODO Why does this need to be imported like this? import { library } from '@fortawesome/fontawesome-svg-core'; -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faTrash } from '@fortawesome/free-solid-svg-icons'; import { faExpandArrowsAlt } from '@fortawesome/free-solid-svg-icons'; import { faCompressArrowsAlt } from '@fortawesome/free-solid-svg-icons'; diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index 7a8dbddcc..648037e31 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -15,7 +15,6 @@ import { Decoration, DecorationSet } from 'prosemirror-view' import { TooltipTextMenu } from "../../util/TooltipTextMenu" import { ContextMenu } from "../../views/ContextMenu"; import { library } from '@fortawesome/fontawesome-svg-core'; -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faEdit } from '@fortawesome/free-solid-svg-icons'; import { faSmile } from '@fortawesome/free-solid-svg-icons'; diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index 62ecea583..7532e23c8 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -1,4 +1,3 @@ - import { action, observable } from 'mobx'; import { observer } from "mobx-react"; import Lightbox from 'react-image-lightbox'; -- cgit v1.2.3-70-g09d2 From c9f3a1934548169ebe3c2e97968680ff339e304e Mon Sep 17 00:00:00 2001 From: Sam Wilkins Date: Sat, 4 May 2019 18:59:30 -0400 Subject: initial commit - todo: use cursor field rather than generic tuple field --- .../northstar/operations/HistogramOperation.ts | 5 +- src/client/util/DragManager.ts | 8 +-- src/client/views/DocumentDecorations.tsx | 2 +- src/client/views/PresentationView.tsx | 4 +- src/client/views/PreviewCursor.tsx | 4 +- .../views/collections/CollectionDockingView.tsx | 6 ++- src/client/views/collections/CollectionSubView.tsx | 9 ++-- .../views/collections/CollectionTreeView.tsx | 4 +- .../views/collections/CollectionVideoView.tsx | 2 +- .../collections/collectionFreeForm/MarqueeView.tsx | 7 +-- .../views/nodes/CollectionFreeFormDocumentView.tsx | 9 ++-- src/client/views/nodes/FormattedTextBox.tsx | 8 +-- src/client/views/nodes/PDFBox.tsx | 5 +- src/new_fields/InkField.ts | 2 +- src/new_fields/ObjectField.ts | 2 +- src/new_fields/TupleField.ts | 63 ++++++++++++++++++++++ 16 files changed, 106 insertions(+), 34 deletions(-) create mode 100644 src/new_fields/TupleField.ts (limited to 'src/client/views/nodes/FormattedTextBox.tsx') diff --git a/src/client/northstar/operations/HistogramOperation.ts b/src/client/northstar/operations/HistogramOperation.ts index 5c9c832c0..78b206bdc 100644 --- a/src/client/northstar/operations/HistogramOperation.ts +++ b/src/client/northstar/operations/HistogramOperation.ts @@ -65,7 +65,7 @@ export class HistogramOperation extends BaseOperation implements IBaseFilterCons @computed public get FilterString(): string { if (this.OverridingFilters.length > 0) { - return "(" + this.OverridingFilters.filter(fm => fm != null).map(fm => fm.ToPythonString()).join(" || ") + ")"; + return "(" + this.OverridingFilters.filter(fm => fm !== null).map(fm => fm.ToPythonString()).join(" || ") + ")"; } let filterModels: FilterModel[] = []; return FilterModel.GetFilterModelsRecursive(this, new Set(), filterModels, true); @@ -89,8 +89,9 @@ export class HistogramOperation extends BaseOperation implements IBaseFilterCons @action public DrillDown(up: boolean) { if (!up) { - if (!this.BarFilterModels.length) + if (!this.BarFilterModels.length) { return; + } this._stackedFilters.push(this.BarFilterModels.map(f => f)); this.OverridingFilters.length = 0; this.OverridingFilters.push(...this._stackedFilters[this._stackedFilters.length - 1]); diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index a3dbe6e43..8f27f5b21 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -155,9 +155,9 @@ export namespace DragManager { export function StartDocumentDrag(eles: HTMLElement[], dragData: DocumentDragData, downX: number, downY: number, options?: DragOptions) { StartDrag(eles, dragData, downX, downY, options, (dropData: { [id: string]: any }) => - (dropData.droppedDocuments = dragData.userDropAction == "alias" || (!dragData.userDropAction && dragData.dropAction == "alias") ? + (dropData.droppedDocuments = dragData.userDropAction === "alias" || (!dragData.userDropAction && dragData.dropAction === "alias") ? dragData.draggedDocuments.map(d => Doc.MakeAlias(d)) : - dragData.userDropAction == "copy" || (!dragData.userDropAction && dragData.dropAction == "copy") ? + dragData.userDropAction === "copy" || (!dragData.userDropAction && dragData.dropAction === "copy") ? dragData.draggedDocuments.map(d => Doc.MakeCopy(d, true)) : dragData.draggedDocuments)); } @@ -280,7 +280,7 @@ export namespace DragManager { }; let hideDragElements = () => { - dragElements.map(dragElement => dragElement.parentNode == dragDiv && dragDiv.removeChild(dragElement)); + dragElements.map(dragElement => dragElement.parentNode === dragDiv && dragDiv.removeChild(dragElement)); eles.map(ele => (ele.hidden = false)); }; let endDrag = () => { @@ -289,7 +289,7 @@ export namespace DragManager { if (options) { options.handlers.dragComplete({}); } - } + }; AbortDrag = () => { hideDragElements(); diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 693d6ec55..16e5b6b48 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -278,7 +278,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> iconDoc = this.createIcon([docView], layout); } if (SelectionManager.SelectedDocuments()[0].props.addDocument !== undefined) { - SelectionManager.SelectedDocuments()[0].props.addDocument!(iconDoc!); + SelectionManager.SelectedDocuments()[0].props.addDocument!(iconDoc); } return iconDoc; } diff --git a/src/client/views/PresentationView.tsx b/src/client/views/PresentationView.tsx index b4c12d057..d8bdbacca 100644 --- a/src/client/views/PresentationView.tsx +++ b/src/client/views/PresentationView.tsx @@ -1,7 +1,7 @@ import { observer } from "mobx-react"; -import React = require("react") +import React = require("react"); import { observable, action } from "mobx"; -import "./PresentationView.scss" +import "./PresentationView.scss"; import "./Main.tsx"; import { DocumentManager } from "../util/DocumentManager"; import { Utils } from "../../Utils"; diff --git a/src/client/views/PreviewCursor.tsx b/src/client/views/PreviewCursor.tsx index 4359ba093..9520f489c 100644 --- a/src/client/views/PreviewCursor.tsx +++ b/src/client/views/PreviewCursor.tsx @@ -17,7 +17,7 @@ export class PreviewCursor extends React.Component<{}> { constructor(props: any) { super(props); - document.addEventListener("keydown", this.onKeyPress) + document.addEventListener("keydown", this.onKeyPress); } @action @@ -27,7 +27,7 @@ export class PreviewCursor extends React.Component<{}> { // the keyPress here. //if not these keys, make a textbox if preview cursor is active! if (e.key.startsWith("F") && !e.key.endsWith("F")) { - } else if (e.key != "Escape" && e.key != "Alt" && e.key != "Shift" && e.key != "Meta" && e.key != "Control" && !e.defaultPrevented && !(e as any).DASHFormattedTextBoxHandled) { + } else if (e.key !== "Escape" && e.key !== "Alt" && e.key !== "Shift" && e.key !== "Meta" && e.key !== "Control" && !e.defaultPrevented && !(e as any).DASHFormattedTextBoxHandled) { if ((!e.ctrlKey && !e.metaKey) || e.key === "v") { PreviewCursor.Visible && PreviewCursor._onKeyPress && PreviewCursor._onKeyPress(e); PreviewCursor.Visible = false; diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index cfb1aef7d..725f0ab51 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -350,13 +350,15 @@ export class DockedFrameRenderer extends React.Component { get previewPanelCenteringOffset() { return (this._panelWidth - this.nativeWidth() * this.contentScaling()) / 2; } get content() { - if (!this._document) + if (!this._document) { return (null); + } return (
- boolean; @@ -66,12 +67,12 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T) { if (!proto) { return; } - let cursors = await Cast(proto.cursors, listSpec(ObjectField)); + let cursors = await Cast(proto!.cursors, listSpec(TupleField)); if (!cursors) { - proto.cursors = cursors = new List(); + proto!.cursors = cursors = new List>(); } - if (cursors.length > 0 && (ind = cursors.findIndex(entry => entry.Data[0][0] === id)) > -1) { - cursors[ind].Data[1] = position; + if (cursors!.length > 0 && (ind = cursors!.findIndex(entry => entry.data[0][0] === id)) > -1) { + cursors![ind].data[1] = position; } else { let entry = new TupleField<[string, string], [number, number]>([textInfo, position]); cursors.push(entry); diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index b67d6f965..7898d74ce 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -117,8 +117,8 @@ class TreeView extends React.Component { } } - onPointerEnter = (e: React.PointerEvent): void => { this.props.document.libraryBrush = true; } - onPointerLeave = (e: React.PointerEvent): void => { this.props.document.libraryBrush = false; } + onPointerEnter = (e: React.PointerEvent): void => { this.props.document.libraryBrush = true; }; + onPointerLeave = (e: React.PointerEvent): void => { this.props.document.libraryBrush = false; }; render() { let bulletType = BulletType.List; diff --git a/src/client/views/collections/CollectionVideoView.tsx b/src/client/views/collections/CollectionVideoView.tsx index 9dee217cb..cb3fd1ba4 100644 --- a/src/client/views/collections/CollectionVideoView.tsx +++ b/src/client/views/collections/CollectionVideoView.tsx @@ -90,7 +90,7 @@ export class CollectionVideoView extends React.Component { } } - setVideoBox = (player: VideoBox) => { this._videoBox = player; } + setVideoBox = (player: VideoBox) => { this._videoBox = player; }; private subView = (_type: CollectionViewType, renderProps: CollectionRenderProps) => { let props = { ...this.props, ...renderProps }; diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 8c81f6990..a9e627188 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -139,7 +139,7 @@ export class MarqueeView extends React.Component if (this._commandExecuted) { return; } - if (e.key === "Backspace" || e.key === "Delete" || e.key == "d") { + if (e.key === "Backspace" || e.key === "Delete" || e.key === "d") { this._commandExecuted = true; this.marqueeSelect().map(d => this.props.removeDocument(d)); let ink = Cast(this.props.container.props.Document.ink, InkField); @@ -154,8 +154,9 @@ export class MarqueeView extends React.Component e.stopPropagation(); let bounds = this.Bounds; let selected = this.marqueeSelect().map(d => { - if (e.key !== "r") + if (e.key !== "r") { this.props.removeDocument(d); + } d.x = NumCast(d.x) - bounds.left - bounds.width / 2; d.y = NumCast(d.y) - bounds.top - bounds.height / 2; d.page = -1; @@ -194,7 +195,7 @@ export class MarqueeView extends React.Component let maxy = NumCast(maximizedDoc.y, undefined); let maxw = NumCast(maximizedDoc.width, undefined); let maxh = NumCast(maximizedDoc.height, undefined); - maximizedDoc.isIconAnimating = new List([scrpt[0], scrpt[1], maxx, maxy, maxw, maxh, Date.now(), 0]) + maximizedDoc.isIconAnimating = new List([scrpt[0], scrpt[1], maxx, maxy, maxw, maxh, Date.now(), 0]); }); } else { diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index 2ba0458f5..6186cf348 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -148,7 +148,7 @@ export class CollectionFreeFormDocumentView extends DocComponent([scrpt[0], scrpt[1], maxx, maxy, maxw, maxh, Date.now(), isMinimized ? 1 : 0]) + maximizedDoc.isIconAnimating = new List([scrpt[0], scrpt[1], maxx, maxy, maxw, maxh, Date.now(), isMinimized ? 1 : 0]); } } }); @@ -167,16 +167,17 @@ export class CollectionFreeFormDocumentView extends DocComponent d instanceof Doc).map(maxDoc => this.props.addDocument!(maxDoc, false)); + } this.toggleIcon(); } } } } - onPointerEnter = (e: React.PointerEvent): void => { this.props.Document.libraryBrush = true; } - onPointerLeave = (e: React.PointerEvent): void => { this.props.Document.libraryBrush = false; } + onPointerEnter = (e: React.PointerEvent): void => { this.props.Document.libraryBrush = true; }; + onPointerLeave = (e: React.PointerEvent): void => { this.props.Document.libraryBrush = false; }; borderRounding = () => { let br = NumCast(this.props.Document.borderRounding); diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index eeb60cb3d..3873dfd62 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -91,7 +91,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe let titlestr = str.substr(0, Math.min(40, str.length)); let target = this.props.Document.proto ? this.props.Document.proto : this.props.Document; target.title = "-" + titlestr + (str.length > 40 ? "..." : ""); - }; + } } } @@ -176,8 +176,9 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe onPointerDown = (e: React.PointerEvent): void => { if (e.button === 0 && this.props.isSelected() && !e.altKey && !e.ctrlKey && !e.metaKey) { e.stopPropagation(); - if (this._toolTipTextMenu && this._toolTipTextMenu.tooltip) + if (this._toolTipTextMenu && this._toolTipTextMenu.tooltip) { this._toolTipTextMenu.tooltip.style.opacity = "0"; + } } if (e.button === 2 || (e.button === 0 && e.ctrlKey)) { this._gotDown = true; @@ -185,8 +186,9 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe } } onPointerUp = (e: React.PointerEvent): void => { - if (this._toolTipTextMenu && this._toolTipTextMenu.tooltip) + if (this._toolTipTextMenu && this._toolTipTextMenu.tooltip) { this._toolTipTextMenu.tooltip.style.opacity = "1"; + } if (e.buttons === 1 && this.props.isSelected() && !e.altKey) { e.stopPropagation(); } diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index eb45ea273..caa66cbeb 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -215,8 +215,9 @@ export class PDFBox extends DocComponent(PdfDocumen if (e.altKey) { this._alt = true; } else { - if (e.metaKey) + if (e.metaKey) { e.stopPropagation(); + } } document.removeEventListener("pointerup", this.onPointerUp); document.addEventListener("pointerup", this.onPointerUp); @@ -286,7 +287,7 @@ export class PDFBox extends DocComponent(PdfDocumen renderHeight = 2400; @computed get pdfPage() { - return + return ; } @computed get pdfContent() { diff --git a/src/new_fields/InkField.ts b/src/new_fields/InkField.ts index 86a8bd18a..a3157857f 100644 --- a/src/new_fields/InkField.ts +++ b/src/new_fields/InkField.ts @@ -39,6 +39,6 @@ export class InkField extends ObjectField { } [Copy]() { - return new InkField(deepCopy(this.inkData)) + return new InkField(deepCopy(this.inkData)); } } diff --git a/src/new_fields/ObjectField.ts b/src/new_fields/ObjectField.ts index 0f3777af6..715c6a924 100644 --- a/src/new_fields/ObjectField.ts +++ b/src/new_fields/ObjectField.ts @@ -5,7 +5,7 @@ export const Parent = Symbol("Parent"); export const Copy = Symbol("Copy"); export abstract class ObjectField { - protected [OnUpdate]?: (diff?: any) => void; + protected [OnUpdate](diff?: any) { }; private [Parent]?: Doc; abstract [Copy](): ObjectField; } diff --git a/src/new_fields/TupleField.ts b/src/new_fields/TupleField.ts new file mode 100644 index 000000000..1ff57fefc --- /dev/null +++ b/src/new_fields/TupleField.ts @@ -0,0 +1,63 @@ +import { ObjectField, Copy } from "./ObjectField"; +import { IObservableArray, IArrayChange, IArraySplice, observe, Lambda, observable } from "mobx"; +import { UndoManager } from "../client/util/UndoManager"; +import { Field } from "./Doc"; +import { Deserializable } from "../client/util/SerializationHelper"; +import { serializable, createSimpleSchema, list, object } from "serializr"; +import { array } from "prop-types"; + +const tupleSchema = createSimpleSchema({ + +}); + +@Deserializable("tuple") +export class TupleField extends ObjectField { + + + @serializable(list(object(tupleSchema))) + private Data: [T, U]; + + public get data() { + return this.Data; + } + + constructor(data: [T, U]) { + super(); + this.Data = data; + this.observeTuple(); + } + + private observeDisposer: Lambda | undefined; + private observeTuple(): void { + this.observeDisposer = observe(this.Data as (T | U)[] as IObservableArray, (change: IArrayChange | IArraySplice) => { + if (change.type === "update") { + UndoManager.AddEvent({ + undo: () => this.Data[change.index] = change.oldValue, + redo: () => this.Data[change.index] = change.newValue + }); + } else { + throw new Error("Why are you messing with the length of a tuple, huh?"); + } + }); + } + + protected setData(value: [T, U]) { + if (this.observeDisposer) { + this.observeDisposer(); + } + this.Data = observable(value) as (T | U)[] as [T, U]; + this.observeTuple(); + } + + UpdateFromServer(values: [T, U]) { + this.setData(values); + } + + ToScriptString(): string { + return `new TupleField([${this.Data[0], this.Data[1]}])`; + } + + [Copy]() { + return new TupleField(this.Data); + } +} \ No newline at end of file -- cgit v1.2.3-70-g09d2 From 9830eb15041fa8e99ef8f5bb6fdcf6b3c28c058d Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Mon, 6 May 2019 01:10:14 -0400 Subject: added start of "minimap" support via better buttons and summaries. --- .../views/collections/CollectionDockingView.tsx | 36 +++++++++++++++++--- .../views/collections/CollectionTreeView.scss | 39 +++++++++++++--------- .../views/collections/CollectionTreeView.tsx | 13 +++++--- .../collections/collectionFreeForm/MarqueeView.tsx | 37 ++++++++++++-------- .../views/nodes/CollectionFreeFormDocumentView.tsx | 28 +++++++++++++--- src/client/views/nodes/DocumentView.tsx | 9 ++--- src/client/views/nodes/FormattedTextBox.tsx | 4 +-- 7 files changed, 118 insertions(+), 48 deletions(-) (limited to 'src/client/views/nodes/FormattedTextBox.tsx') diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 278065479..e4f02a4bc 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -72,6 +72,37 @@ export class CollectionDockingView extends React.Component { + if (child.contentItems.length === 1 && child.contentItems[0].config.component === "DocumentFrameRenderer" && + child.contentItems[0].config.props.documentId == document[Id]) { + child.contentItems[0].remove(); + //this._goldenLayout.root.contentItems[0].contentItems.splice(i, 1); + this.layoutChanged(document); + } else + child.contentItems.map((tab: any, j: number) => { + if (tab.config.component === "DocumentFrameRenderer" && tab.config.props.documentId === document[Id]) { + child.contentItems[j].remove(); + let docs = Cast(this.props.Document.data, listSpec(Doc)); + docs && docs.indexOf(document) !== -1 && docs.splice(docs.indexOf(document), 1); + } + }); + }) + } + } + + @action + layoutChanged(removed?: Doc) { + this._goldenLayout.root.callDownwards('setSize', [this._goldenLayout.width, this._goldenLayout.height]); + this._goldenLayout.emit('sbcreteChanged'); + this._ignoreStateChange = JSON.stringify(this._goldenLayout.toConfig()); + if (removed) CollectionDockingView.Instance._removedDocs.push(removed); + this.stateChanged(); + } + // // Creates a vertical split on the right side of the docking view, and then adds the Document to that split // @@ -107,10 +138,7 @@ export class CollectionDockingView extends React.Component { @observable _collapsed: boolean = true; delete = () => this.props.deleteDoc(this.props.document); + openRight = () => CollectionDockingView.Instance.AddRightSplit(this.props.document); get children() { return Cast(this.props.document.data, listSpec(Doc), []); // bcz: needed? .filter(doc => FieldValue(doc)); @@ -100,9 +102,11 @@ class TreeView extends React.Component { }} />); return ( -
+
{editableView(StrCast(this.props.document.title))} - {/*
*/} +
+ {/* {
} */}
); } @@ -145,8 +149,7 @@ class TreeView extends React.Component { }); return
+ onContextMenu={this.onWorkspaceContextMenu}>
  • {this.renderBullet(bulletType)} {this.renderTitle()} diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 8c81f6990..805921ad4 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -15,6 +15,8 @@ import { NumCast, Cast } from "../../../../new_fields/Types"; import { InkField, StrokeData } from "../../../../new_fields/InkField"; import { Templates } from "../../Templates"; import { List } from "../../../../new_fields/List"; +import { emitKeypressEvents } from "readline"; +import { listSpec } from "../../../../new_fields/Schema"; interface MarqueeViewProps { getContainerTransform: () => Transform; @@ -149,16 +151,17 @@ export class MarqueeView extends React.Component this.cleanupInteractions(false); e.stopPropagation(); } - if (e.key === "c" || e.key === "r" || e.key === "e") { + if (e.key === "c" || e.key === "r" || e.key === "R" || e.key === "e") { this._commandExecuted = true; e.stopPropagation(); let bounds = this.Bounds; let selected = this.marqueeSelect().map(d => { - if (e.key !== "r") + if (e.key !== "R") { this.props.removeDocument(d); - d.x = NumCast(d.x) - bounds.left - bounds.width / 2; - d.y = NumCast(d.y) - bounds.top - bounds.height / 2; - d.page = -1; + d.x = NumCast(d.x) - bounds.left - bounds.width / 2; + d.y = NumCast(d.y) - bounds.top - bounds.height / 2; + d.page = -1; + } return d; }); let ink = Cast(this.props.container.props.Document.ink, InkField); @@ -179,16 +182,23 @@ export class MarqueeView extends React.Component this.marqueeInkDelete(inkData); // SelectionManager.DeselectAll(); - if (e.key === "r") { - let summary = Docs.TextDocument({ x: bounds.left, y: bounds.top, width: 300, height: 100, backgroundColor: "yellow", title: "-summary-" }); - summary.maximizedDocs = new List(selected); - // summary.doc1 = selected[0]; - // if (selected.length > 1) - // summary.doc2 = selected[1]; - // summary.templates = new List([Templates.Summary.Layout]); - this.props.addLiveTextDocument(summary); + if (e.key === "r" || e.key === "R") { e.preventDefault(); let scrpt = this.props.getTransform().inverse().transformPoint(bounds.left, bounds.top); + let summary = Docs.TextDocument({ x: bounds.left, y: bounds.top, width: 300, height: 100, backgroundColor: "yellow", title: "-summary-" }); + + if (e.key === "r") { + summary.proto!.maximizeOnRight = true; + let list = Cast(newCollection.data, listSpec(Doc)); + if (list && list.length === 1) { + selected = list; + } else { + selected = [newCollection]; + this.props.addDocument(newCollection, false); + } + } + summary.proto!.maximizedDocs = new List(selected); + summary.proto!.isButton = true; selected.map(maximizedDoc => { let maxx = NumCast(maximizedDoc.x, undefined); let maxy = NumCast(maximizedDoc.y, undefined); @@ -196,6 +206,7 @@ export class MarqueeView extends React.Component let maxh = NumCast(maximizedDoc.height, undefined); maximizedDoc.isIconAnimating = new List([scrpt[0], scrpt[1], maxx, maxy, maxw, maxh, Date.now(), 0]) }); + this.props.addLiveTextDocument(summary); } else { this.props.addDocument(newCollection, false); diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index 2ba0458f5..cf08c1bc4 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -6,11 +6,12 @@ import "./DocumentView.scss"; import React = require("react"); import { DocComponent } from "../DocComponent"; import { createSchema, makeInterface, listSpec } from "../../../new_fields/Schema"; -import { FieldValue, Cast, NumCast, BoolCast } from "../../../new_fields/Types"; +import { FieldValue, Cast, NumCast, BoolCast, PromiseValue } from "../../../new_fields/Types"; import { OmitKeys, Utils } from "../../../Utils"; import { SelectionManager } from "../../util/SelectionManager"; import { Doc } from "../../../new_fields/Doc"; import { List } from "../../../new_fields/List"; +import { CollectionDockingView } from "../collections/CollectionDockingView"; export interface CollectionFreeFormDocumentViewProps extends DocumentViewProps { } @@ -86,7 +87,7 @@ export class CollectionFreeFormDocumentView extends DocComponent { e.stopPropagation(); let ctrlKey = e.ctrlKey; + let metaKey = e.metaKey; if (Math.abs(e.clientX - this._downX) < Utils.DRAG_THRESHOLD && Math.abs(e.clientY - this._downY) < Utils.DRAG_THRESHOLD) { if (await BoolCast(this.props.Document.isButton, false)) { let maximizedDocs = await Cast(this.props.Document.maximizedDocs, listSpec(Doc)); if (maximizedDocs) { // bcz: need a better way to associate behaviors with click events on widget-documents - if (ctrlKey) - this.props.addDocument && maximizedDocs.filter(d => d instanceof Doc).map(maxDoc => this.props.addDocument!(maxDoc, false)); - this.toggleIcon(); + if ((metaKey && !this.props.Document.maximizeOnRight) || (!metaKey && this.props.Document.maximizeOnRight)) { + SelectionManager.DeselectAll(); + maximizedDocs.map(async mdoc => { + let maxDoc = await mdoc; + let dataDocs = await Cast(CollectionDockingView.Instance.props.Document.data, listSpec(Doc)); + if (dataDocs) { + Promise.all(dataDocs.map(async doc => await doc)).then(docs => { + if (!docs || docs.indexOf(maxDoc) == -1) { + CollectionDockingView.Instance.AddRightSplit(maxDoc); + } else { + CollectionDockingView.Instance.CloseRightSplit(maxDoc); + } + }) + } + }); + } else { + this.props.addDocument && maximizedDocs.map(async maxDoc => this.props.addDocument!(await maxDoc, false)); + this.toggleIcon(); + } } } } diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 096a02d9b..9d356cc30 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -202,10 +202,11 @@ export class DocumentView extends DocComponent(Docu CollectionDockingView.Instance.AddRightSplit(kvp); } makeButton = (e: React.MouseEvent): void => { - this.props.Document.isButton = !BoolCast(this.props.Document.isButton, false); - if (this.props.Document.isButton && !this.props.Document.nativeWidth) { - this.props.Document.nativeWidth = this.props.Document[WidthSym](); - this.props.Document.nativeHeight = this.props.Document[HeightSym](); + let doc = this.props.Document.proto ? this.props.Document.proto : this.props.Document; + doc.isButton = !BoolCast(doc.isButton, false); + if (doc.isButton && !doc.nativeWidth) { + doc.nativeWidth = doc[WidthSym](); + doc.nativeHeight = doc[HeightSym](); } } fullScreenClicked = (e: React.MouseEvent): void => { diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index eeb60cb3d..65b8b805f 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -128,7 +128,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe ); } else { this._proxyReactionDisposer = reaction(() => this.props.isSelected(), - () => this.props.isSelected() && !BoolCast(this.props.Document.isButton, false) && MainOverlayTextBox.Instance.SetTextDoc(this.props.Document, this.props.fieldKey, this._ref.current!, this.props.ScreenToLocalTransform)); + () => this.props.isSelected() && MainOverlayTextBox.Instance.SetTextDoc(this.props.Document, this.props.fieldKey, this._ref.current!, this.props.ScreenToLocalTransform)); } @@ -310,7 +310,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe // tfs: do we need this event handler onWheel={this.onPointerWheel} > -
    +
    ); } -- cgit v1.2.3-70-g09d2 From 337335bc3f7daa61ca9116feaec85882ffd0853a Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Mon, 6 May 2019 23:50:59 -0400 Subject: added some undo support for creating and editing text boxes --- .../views/collections/collectionFreeForm/MarqueeView.tsx | 5 ++++- src/client/views/nodes/FormattedTextBox.tsx | 13 ++++++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) (limited to 'src/client/views/nodes/FormattedTextBox.tsx') diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 805921ad4..0484c181e 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -3,7 +3,7 @@ import { observer } from "mobx-react"; import { Docs } from "../../../documents/Documents"; import { SelectionManager } from "../../../util/SelectionManager"; import { Transform } from "../../../util/Transform"; -import { undoBatch } from "../../../util/UndoManager"; +import { undoBatch, UndoManager } from "../../../util/UndoManager"; import { InkingCanvas } from "../../InkingCanvas"; import { PreviewCursor } from "../../PreviewCursor"; import { CollectionFreeFormView } from "./CollectionFreeFormView"; @@ -17,6 +17,8 @@ import { Templates } from "../../Templates"; import { List } from "../../../../new_fields/List"; import { emitKeypressEvents } from "readline"; import { listSpec } from "../../../../new_fields/Schema"; +import { undo } from "prosemirror-history"; +import { FormattedTextBox } from "../../nodes/FormattedTextBox"; interface MarqueeViewProps { getContainerTransform: () => Transform; @@ -50,6 +52,7 @@ export class MarqueeView extends React.Component this._visible = false; } + @undoBatch @action onKeyPress = (e: KeyboardEvent) => { //make textbox and add it to this collection diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index 65b8b805f..ffd68fd48 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -23,6 +23,7 @@ import { InkingControl } from "../InkingControl"; import { StrCast, Cast, NumCast, BoolCast } from "../../../new_fields/Types"; import { RichTextField } from "../../../new_fields/RichTextField"; import { Id } from "../../../new_fields/RefField"; +import { UndoManager } from "../../util/UndoManager"; const { buildMenuItems } = require("prosemirror-example-setup"); const { menuBar } = require("prosemirror-menu"); @@ -271,7 +272,13 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe } }); } - + onBlur = (e: any) => { + if (this._undoTyping) { + this._undoTyping.end(); + this._undoTyping = undefined; + } + } + public _undoTyping?: UndoManager.Batch; onKeyPress = (e: React.KeyboardEvent) => { if (e.key === "Escape") { SelectionManager.DeselectAll(); @@ -287,6 +294,9 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe let target = this.props.Document.proto ? this.props.Document.proto : this.props.Document; target.title = "-" + titlestr + (str.length > 40 ? "..." : ""); } + if (!this._undoTyping) { + this._undoTyping = UndoManager.StartBatch("undoTyping"); + } } render() { let style = this.props.isOverlay ? "scroll" : "hidden"; @@ -303,6 +313,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe onKeyPress={this.onKeyPress} onFocus={this.onFocused} onClick={this.onClick} + onBlur={this.onBlur} onPointerUp={this.onPointerUp} onPointerDown={this.onPointerDown} onMouseDown={this.onMouseDown} -- cgit v1.2.3-70-g09d2 From dc9275ec0308ecca1246942a1cf9ef342e9e3300 Mon Sep 17 00:00:00 2001 From: bob Date: Tue, 7 May 2019 13:48:49 -0400 Subject: changed css for text background colors. made api to add text to new textboxes.. added ctrl-q to paste text in boxes based on "paragraph" recognition rules. --- src/client/documents/Documents.ts | 2 +- src/client/views/PreviewCursor.tsx | 2 +- .../collections/collectionFreeForm/MarqueeView.tsx | 23 ++++++++++++++++++++-- src/client/views/globalCssVariables.scss | 2 +- src/client/views/nodes/FormattedTextBox.scss | 2 +- src/client/views/nodes/FormattedTextBox.tsx | 5 +++++ 6 files changed, 30 insertions(+), 6 deletions(-) (limited to 'src/client/views/nodes/FormattedTextBox.tsx') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 37d263e75..a770ccc93 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -132,7 +132,7 @@ export namespace Docs { } function CreateTextPrototype(): Doc { let textProto = setupPrototypeOptions(textProtoId, "TEXT_PROTO", FormattedTextBox.LayoutString(), - { x: 0, y: 0, width: 300, height: 150 }); + { x: 0, y: 0, width: 300, height: 150, backgroundColor: "#f1efeb" }); return textProto; } function CreatePdfPrototype(): Doc { diff --git a/src/client/views/PreviewCursor.tsx b/src/client/views/PreviewCursor.tsx index 4359ba093..4ac4b9c95 100644 --- a/src/client/views/PreviewCursor.tsx +++ b/src/client/views/PreviewCursor.tsx @@ -28,7 +28,7 @@ export class PreviewCursor extends React.Component<{}> { //if not these keys, make a textbox if preview cursor is active! if (e.key.startsWith("F") && !e.key.endsWith("F")) { } else if (e.key != "Escape" && e.key != "Alt" && e.key != "Shift" && e.key != "Meta" && e.key != "Control" && !e.defaultPrevented && !(e as any).DASHFormattedTextBoxHandled) { - if ((!e.ctrlKey && !e.metaKey) || e.key === "v") { + if ((!e.ctrlKey && !e.metaKey) || e.key === "v" || e.key === "q") { PreviewCursor.Visible && PreviewCursor._onKeyPress && PreviewCursor._onKeyPress(e); PreviewCursor.Visible = false; } diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 0484c181e..c9b0b28f7 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -57,8 +57,27 @@ export class MarqueeView extends React.Component onKeyPress = (e: KeyboardEvent) => { //make textbox and add it to this collection let [x, y] = this.props.getTransform().transformPoint(this._downX, this._downY); - let newBox = Docs.TextDocument({ width: 200, height: 100, x: x, y: y, title: "-typed text-" }); - this.props.addLiveTextDocument(newBox); + if (e.key === "q" && e.ctrlKey) { + e.preventDefault(); + (async () => { + let text = await navigator.clipboard.readText(); + let ns = text.split("\n").filter(t => t != "\r"); + for (let i = 0; i < ns.length - 1; i++) { + while (!(ns[i].endsWith("-\r") || ns[i].endsWith(".\r") || ns[i].endsWith(":\r")) && i < ns.length - 1) { + ns.splice(i, 2, ns[i].substr(0, ns[i].length - 1) + ns[i + 1].trimLeft()); + } + } + ns.map(line => { + let indent = line.search(/\S|$/); + let newBox = Docs.TextDocument({ width: 200, height: 35, x: x + indent / 3 * 10, y: y, documentText: "@@@" + line, title: line }); + this.props.addDocument(newBox, false); + y += 40 * this.props.getTransform().Scale; + }) + })(); + } else { + let newBox = Docs.TextDocument({ width: 200, height: 100, x: x, y: y, title: "-typed text-" }); + this.props.addLiveTextDocument(newBox); + } e.stopPropagation(); } @action diff --git a/src/client/views/globalCssVariables.scss b/src/client/views/globalCssVariables.scss index 4f68b71b0..cb4d1ad87 100644 --- a/src/client/views/globalCssVariables.scss +++ b/src/client/views/globalCssVariables.scss @@ -1,7 +1,7 @@ @import url("https://fonts.googleapis.com/css?family=Noto+Sans:400,700|Crimson+Text:400,400i,700"); // colors $light-color: #fcfbf7; -$light-color-secondary: rgb(241, 239, 235); +$light-color-secondary:#f1efeb; $main-accent: #61aaa3; // $alt-accent: #cdd5ec; // $alt-accent: #cdeceb; diff --git a/src/client/views/nodes/FormattedTextBox.scss b/src/client/views/nodes/FormattedTextBox.scss index d43aa4e02..9e58a8e7f 100644 --- a/src/client/views/nodes/FormattedTextBox.scss +++ b/src/client/views/nodes/FormattedTextBox.scss @@ -11,7 +11,7 @@ } .formattedTextBox-cont-scroll, .formattedTextBox-cont-hidden { - background: $light-color-secondary; + background: inherit; padding: 0; border-width: 0px; border-radius: inherit; diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index ffd68fd48..8d2f1c780 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -151,6 +151,11 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe state: field && field.Data ? EditorState.fromJSON(config, JSON.parse(field.Data)) : EditorState.create(config), dispatchTransaction: this.dispatchTransaction }); + let text = StrCast(this.props.Document.documentText); + if (text.startsWith("@@@")) { + this.props.Document.proto!.documentText = undefined; + this._editorView.dispatch(this._editorView.state.tr.insertText(text.substr(3))); + } } if (this.props.selectOnLoad) { -- cgit v1.2.3-70-g09d2 From c67fc234cf4a524c19989134d878797563207e93 Mon Sep 17 00:00:00 2001 From: bob Date: Wed, 8 May 2019 16:05:02 -0400 Subject: fixes for templates and for dragging --- src/client/util/DragManager.ts | 16 +++++++++------- .../collectionFreeForm/CollectionFreeFormView.tsx | 12 ++++-------- .../views/nodes/CollectionFreeFormDocumentView.tsx | 2 +- src/client/views/nodes/DocumentContentsView.tsx | 13 +++++++------ src/client/views/nodes/FormattedTextBox.tsx | 2 +- 5 files changed, 22 insertions(+), 23 deletions(-) (limited to 'src/client/views/nodes/FormattedTextBox.tsx') diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index a3dbe6e43..ec192eaff 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -3,7 +3,7 @@ import { emptyFunction } from "../../Utils"; import { CollectionDockingView } from "../views/collections/CollectionDockingView"; import * as globalCssVariables from "../views/globalCssVariables.scss"; import { MainOverlayTextBox } from "../views/MainOverlayTextBox"; -import { Doc } from "../../new_fields/Doc"; +import { Doc, DocListCast } from "../../new_fields/Doc"; import { Cast } from "../../new_fields/Types"; import { listSpec } from "../../new_fields/Schema"; @@ -42,12 +42,14 @@ export function SetupDrag(_reference: React.RefObject, docFunc: export async function DragLinksAsDocuments(dragEle: HTMLElement, x: number, y: number, sourceDoc: Doc) { let srcTarg = sourceDoc.proto; - let draggedDocs = srcTarg ? - Cast(srcTarg.linkedToDocs, listSpec(Doc), []).map(linkDoc => - Cast(linkDoc.linkedTo, Doc) as Doc) : []; - let draggedFromDocs = srcTarg ? - Cast(srcTarg.linkedFromDocs, listSpec(Doc), []).map(linkDoc => - Cast(linkDoc.linkedFrom, Doc) as Doc) : []; + let draggedDocs: Doc[] = []; + let draggedFromDocs: Doc[] = [] + if (srcTarg) { + let linkToDocs = await DocListCast(srcTarg.linkedToDocs); + let linkFromDocs = await DocListCast(srcTarg.linkedFromDocs); + if (linkToDocs) draggedDocs = linkToDocs.map(linkDoc => Cast(linkDoc.linkedTo, Doc) as Doc); + if (linkFromDocs) draggedFromDocs = linkFromDocs.map(linkDoc => Cast(linkDoc.linkedFrom, Doc) as Doc); + } draggedDocs.push(...draggedFromDocs); if (draggedDocs.length) { let moddrag: Doc[] = []; diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 7fa945891..fcc73d5b6 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -326,10 +326,8 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { @observer class CollectionFreeFormOverlayView extends React.Component { @computed get overlayView() { - let overlayLayout = Cast(this.props.Document.overlayLayout, "string", ""); - return !overlayLayout ? (null) : - (); + return (); } render() { return this.overlayView; @@ -339,10 +337,8 @@ class CollectionFreeFormOverlayView extends React.Component { @observer class CollectionFreeFormBackgroundView extends React.Component boolean }> { @computed get backgroundView() { - let backgroundLayout = Cast(this.props.Document.backgroundLayout, "string", ""); - return !backgroundLayout ? (null) : - (); + return (); } render() { return this.backgroundView; diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index 1f8d22ab0..470c0c2f8 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -170,7 +170,7 @@ export class CollectionFreeFormDocumentView extends DocComponent { this._downX = e.clientX; this._downY = e.clientY; - e.stopPropagation(); + // e.stopPropagation(); } onClick = async (e: React.MouseEvent) => { e.stopPropagation(); diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx index 294e17720..f404b7bc6 100644 --- a/src/client/views/nodes/DocumentContentsView.tsx +++ b/src/client/views/nodes/DocumentContentsView.tsx @@ -1,4 +1,4 @@ -import { computed } from "mobx"; +import { computed, trace } from "mobx"; import { observer } from "mobx-react"; import { CollectionDockingView } from "../collections/CollectionDockingView"; import { CollectionFreeFormView } from "../collections/collectionFreeForm/CollectionFreeFormView"; @@ -45,7 +45,7 @@ export class DocumentContentsView extends React.Component void, layoutKey: string }> { - @computed get layout(): string { return Cast(this.props.Document[this.props.layoutKey], "string", "

    Error loading layout data

    "); } + @computed get layout(): string { return Cast(this.props.Document[this.props.layoutKey], "string", this.props.layoutKey === "layout" ? "

    Error loading layout data

    " : ""); } CreateBindings(): JsxBindings { return { props: OmitKeys(this.props, ['parentActive'], (obj: any) => obj.active = this.props.parentActive).omit }; @@ -58,17 +58,17 @@ export class DocumentContentsView extends React.Component(); } - set templates(templates: List) { this.props.Document.templates = templates; } - get finalLayout() { + @computed get finalLayout() { const baseLayout = this.layout; let base = baseLayout; let layout = baseLayout; - // bcz: templates are intended only for a document's primary layout (not background). However, + // bcz: templates are intended only for a document's primary layout or overlay (not background). However, // a DocumentContentsView is used to render annotation overlays, so we detect that here // by checking the layoutKey. This should probably be moved into // a prop so that the overlay can explicitly turn off templates. - if (this.props.layoutKey !== "backgroundLayout") { + if ((this.props.layoutKey === "overlayLayout" && StrCast(this.props.Document.layout).indexOf("CollectionView") !== -1) || + (this.props.layoutKey === "layout" && StrCast(this.props.Document.layout).indexOf("CollectionView") === -1)) { this.templates.forEach(template => { let self = this; function convertConstantsToNative(match: string, offset: number, x: string) { @@ -84,6 +84,7 @@ export class DocumentContentsView extends React.Component Date: Wed, 8 May 2019 18:31:14 -0400 Subject: fixes for templates including changing the relative order of CollectionOverlayView in the stack --- src/client/views/MainOverlayTextBox.tsx | 1 + src/client/views/Templates.tsx | 2 +- .../collectionFreeForm/CollectionFreeFormLinksView.tsx | 2 +- .../collectionFreeForm/CollectionFreeFormView.scss | 8 ++++++-- .../collectionFreeForm/CollectionFreeFormView.tsx | 15 +++++---------- .../views/collections/collectionFreeForm/MarqueeView.tsx | 3 +++ src/client/views/nodes/FormattedTextBox.scss | 1 + src/client/views/nodes/FormattedTextBox.tsx | 6 ++---- 8 files changed, 20 insertions(+), 18 deletions(-) (limited to 'src/client/views/nodes/FormattedTextBox.tsx') diff --git a/src/client/views/MainOverlayTextBox.tsx b/src/client/views/MainOverlayTextBox.tsx index d32e3f21b..3b75c248a 100644 --- a/src/client/views/MainOverlayTextBox.tsx +++ b/src/client/views/MainOverlayTextBox.tsx @@ -43,6 +43,7 @@ export class MainOverlayTextBox extends React.Component this._textXf = tx ? tx : () => Transform.Identity(); this._textTargetDiv = div; if (div) { + if (div.parentElement && div.parentElement instanceof HTMLDivElement && div.parentElement.id === "screenSpace") this._textXf = () => Transform.Identity(); this._textColor = div.style.color; div.style.color = "transparent"; this.TextScroll = div.scrollTop; diff --git a/src/client/views/Templates.tsx b/src/client/views/Templates.tsx index 6f706bdc5..02f9aa510 100644 --- a/src/client/views/Templates.tsx +++ b/src/client/views/Templates.tsx @@ -39,7 +39,7 @@ export namespace Templates { // export const BasicLayout = new Template("Basic layout", "{layout}"); export const OuterCaption = new Template("Outer caption", TemplatePosition.OutterBottom, - `
    {layout}
    ` + `
    ` ); export const InnerCaption = new Template("Inner caption", TemplatePosition.InnerBottom, diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx index 2d815a302..cbfbb1d2c 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx @@ -1,4 +1,4 @@ -import { computed, IReactionDisposer, reaction } from "mobx"; +import { computed, IReactionDisposer, reaction, trace } from "mobx"; import { observer } from "mobx-react"; import { Utils } from "../../../../Utils"; import { DocumentManager } from "../../../util/DocumentManager"; diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss index cb849b325..063c9e2cf 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss @@ -37,7 +37,9 @@ border-radius: $border-radius; box-sizing: border-box; position: absolute; - overflow: hidden; + .marqueeView { + overflow: hidden; + } top: 0; left: 0; width: 100%; @@ -61,7 +63,9 @@ border-radius: $border-radius; box-sizing: border-box; position:absolute; - overflow: hidden; + .marqueeView { + overflow: hidden; + } top: 0; left: 0; width: 100%; diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index fcc73d5b6..797f94d5f 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -110,15 +110,11 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { @action onPointerDown = (e: React.PointerEvent): void => { - let childSelected = Cast(this.props.Document[this.props.fieldKey], listSpec(Doc), [] as Doc[]).filter(doc => doc).reduce((childSelected, doc) => { - var dv = DocumentManager.Instance.getDocumentView(doc); - return childSelected || (dv && SelectionManager.IsSelected(dv) ? true : false); - }, false); if ((CollectionFreeFormView.RIGHT_BTN_DRAG && (((e.button === 2 && (!this.isAnnotationOverlay || this.zoomScaling() !== 1)) || - (e.button === 0 && e.altKey)) && (childSelected || this.props.active()))) || + (e.button === 0 && e.altKey)) && this.props.active())) || (!CollectionFreeFormView.RIGHT_BTN_DRAG && - ((e.button === 0 && !e.altKey && (!this.isAnnotationOverlay || this.zoomScaling() !== 1)) && (childSelected || this.props.active())))) { + ((e.button === 0 && !e.altKey && (!this.isAnnotationOverlay || this.zoomScaling() !== 1)) && this.props.active()))) { document.removeEventListener("pointermove", this.onPointerMove); document.removeEventListener("pointerup", this.onPointerUp); document.addEventListener("pointermove", this.onPointerMove); @@ -233,7 +229,6 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { return NumCast(doc1.zIndex) - NumCast(doc2.zIndex); }).forEach((doc, index) => doc.zIndex = index + 1); doc.zIndex = docs.length + 1; - return doc; } focusDocument = (doc: Doc) => { @@ -316,18 +311,18 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { {/* */} - +
    ); } } @observer -class CollectionFreeFormOverlayView extends React.Component { +class CollectionFreeFormOverlayView extends React.Component boolean }> { @computed get overlayView() { return (); + isTopMost={this.props.isTopMost} isSelected={this.props.isSelected} select={emptyFunction} />); } render() { return this.overlayView; diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 9764db1d4..740c50297 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -101,6 +101,8 @@ export class MarqueeView extends React.Component document.addEventListener("pointermove", this.onPointerMove, true); document.addEventListener("pointerup", this.onPointerUp, true); document.addEventListener("keydown", this.marqueeCommand, true); + console.log(this.props.container.props.Document.title); + e.stopPropagation(); } if (e.altKey) { e.preventDefault(); @@ -180,6 +182,7 @@ export class MarqueeView extends React.Component if (ink) { this.marqueeInkDelete(ink.inkData); } + SelectionManager.DeselectAll(); this.cleanupInteractions(false); e.stopPropagation(); } diff --git a/src/client/views/nodes/FormattedTextBox.scss b/src/client/views/nodes/FormattedTextBox.scss index 9e58a8e7f..458a62c5b 100644 --- a/src/client/views/nodes/FormattedTextBox.scss +++ b/src/client/views/nodes/FormattedTextBox.scss @@ -17,6 +17,7 @@ border-radius: inherit; border-color: $intermediate-color; box-sizing: border-box; + background-color: inherit; border-style: solid; overflow-y: scroll; overflow-x: hidden; diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index ee6000da7..4b3172e82 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -24,8 +24,8 @@ import { StrCast, Cast, NumCast, BoolCast } from "../../../new_fields/Types"; import { RichTextField } from "../../../new_fields/RichTextField"; import { Id } from "../../../new_fields/RefField"; import { UndoManager } from "../../util/UndoManager"; -const { buildMenuItems } = require("prosemirror-example-setup"); -const { menuBar } = require("prosemirror-menu"); +import { Transform } from "prosemirror-transform"; +import { Transform as MatrixTransform } from "../../util/Transform"; // FormattedTextBox: Displays an editable plain text node that maps to a specified Key of a Document // @@ -306,13 +306,11 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe render() { let style = this.props.isOverlay ? "scroll" : "hidden"; let rounded = NumCast(this.props.Document.borderRounding) < 0 ? "-rounded" : ""; - let color = StrCast(this.props.Document.backgroundColor); let interactive = InkingControl.Instance.selectedTool ? "" : "interactive"; return (
    Date: Wed, 8 May 2019 23:52:13 -0400 Subject: added imageResize handle in text boxes. --- src/client/util/RichTextSchema.tsx | 85 +++++++++++++++++++++- src/client/util/TooltipTextMenu.tsx | 1 + .../collections/collectionFreeForm/MarqueeView.tsx | 6 +- src/client/views/nodes/FormattedTextBox.tsx | 22 ++---- 4 files changed, 91 insertions(+), 23 deletions(-) (limited to 'src/client/views/nodes/FormattedTextBox.tsx') diff --git a/src/client/util/RichTextSchema.tsx b/src/client/util/RichTextSchema.tsx index 9ef71e305..c036bfe97 100644 --- a/src/client/util/RichTextSchema.tsx +++ b/src/client/util/RichTextSchema.tsx @@ -84,6 +84,7 @@ export const nodes: { [index: string]: NodeSpec } = { inline: true, attrs: { src: {}, + width: { default: "100px" }, alt: { default: null }, title: { default: null } }, @@ -94,11 +95,16 @@ export const nodes: { [index: string]: NodeSpec } = { return { src: dom.getAttribute("src"), title: dom.getAttribute("title"), - alt: dom.getAttribute("alt") - }; + alt: dom.getAttribute("alt"), + width: Math.min(100, Number(dom.getAttribute("width"))), + } } }], - toDOM(node: any) { return ["img", node.attrs]; } + // TODO if we don't define toDom, something weird happens: dragging the image will not move it but clone it. Why? + toDOM(node) { + const attrs = { style: `width: ${node.attrs.width}` } + return ["img", { ...node.attrs, ...attrs }] + } }, // :: NodeSpec A hard line break, represented in the DOM as `
    `. @@ -290,6 +296,13 @@ export const marks: { [index: string]: MarkSpec } = { }] }, + p14: { + parseDOM: [{ style: 'font-size: 14px;' }], + toDOM: () => ['span', { + style: 'font-size: 14px;' + }] + }, + p16: { parseDOM: [{ style: 'font-size: 16px;' }], toDOM: () => ['span', { @@ -325,7 +338,73 @@ export const marks: { [index: string]: MarkSpec } = { }] }, }; +function getFontSize(element: any) { + return parseFloat((getComputedStyle(element) as any).fontSize); +} + +export class ImageResizeView { + _handle: HTMLElement; + _img: HTMLElement; + _outer: HTMLElement; + constructor(node: any, view: any, getPos: any) { + this._handle = document.createElement("span"); + this._img = document.createElement("img"); + this._outer = document.createElement("span"); + this._outer.style.position = "relative"; + this._outer.style.width = node.attrs.width; + this._outer.style.display = "inline-block"; + this._outer.style.overflow = "hidden"; + + this._img.setAttribute("src", node.attrs.src); + this._img.style.width = "100%"; + this._handle.style.position = "absolute"; + this._handle.style.width = "20px"; + this._handle.style.height = "20px"; + this._handle.style.backgroundColor = "blue"; + this._handle.style.borderRadius = "15px"; + this._handle.style.display = "none"; + this._handle.style.bottom = "-10px"; + this._handle.style.right = "-10px"; + let self = this; + this._handle.onpointerdown = function (e: any) { + e.preventDefault(); + const startX = e.pageX; + const startWidth = parseFloat(node.attrs.width); + const onpointermove = (e: any) => { + const currentX = e.pageX; + const diffInPx = currentX - startX; + self._outer.style.width = `${startWidth + diffInPx}`; + } + + const onpointerup = () => { + document.removeEventListener("pointermove", onpointermove); + document.removeEventListener("pointerup", onpointerup); + view.dispatch( + view.state.tr.setNodeMarkup(getPos(), null, + { src: node.attrs.src, width: self._outer.style.width })); + } + + document.addEventListener("pointermove", onpointermove) + document.addEventListener("pointerup", onpointerup) + } + this._outer.appendChild(this._handle); + this._outer.appendChild(this._img); + (this as any).dom = this._outer; + } + + selectNode() { + this._img.classList.add("ProseMirror-selectednode"); + + this._handle.style.display = ""; + } + + deselectNode() { + this._img.classList.remove("ProseMirror-selectednode"); + + this._handle.style.display = "none"; + } +} // :: Schema // This schema rougly corresponds to the document schema used by // [CommonMark](http://commonmark.org/), minus the list elements, diff --git a/src/client/util/TooltipTextMenu.tsx b/src/client/util/TooltipTextMenu.tsx index 68a73375e..e33c53a1a 100644 --- a/src/client/util/TooltipTextMenu.tsx +++ b/src/client/util/TooltipTextMenu.tsx @@ -94,6 +94,7 @@ export class TooltipTextMenu { this.fontSizeToNum = new Map(); this.fontSizeToNum.set(schema.marks.p10, 10); this.fontSizeToNum.set(schema.marks.p12, 12); + this.fontSizeToNum.set(schema.marks.p14, 14); this.fontSizeToNum.set(schema.marks.p16, 16); this.fontSizeToNum.set(schema.marks.p24, 24); this.fontSizeToNum.set(schema.marks.p32, 32); diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 0345d5efd..6057aaeba 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -180,7 +180,7 @@ export class MarqueeView extends React.Component this.cleanupInteractions(false); e.stopPropagation(); } - if (e.key === "c" || e.key === "r" || e.key === "s" || e.key === "e") { + if (e.key === "c" || e.key === "r" || e.key === "s" || e.key === "e" || e.key === "p") { this._commandExecuted = true; e.stopPropagation(); let bounds = this.Bounds; @@ -218,12 +218,12 @@ export class MarqueeView extends React.Component this.marqueeInkDelete(inkData); // SelectionManager.DeselectAll(); - if (e.key === "s" || e.key === "r") { + if (e.key === "s" || e.key === "r" || e.key === "p") { e.preventDefault(); let scrpt = this.props.getTransform().inverse().transformPoint(bounds.left, bounds.top); let summary = Docs.TextDocument({ x: bounds.left, y: bounds.top, width: 300, height: 100, backgroundColor: "yellow", title: "-summary-" }); - if (e.key === "s") { + if (e.key === "s" || e.key === "p") { summary.proto!.maximizeOnRight = true; newCollection.proto!.summaryDoc = summary; selected = [newCollection]; diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index 4b3172e82..445a834ee 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -6,7 +6,7 @@ import { EditorState, Plugin, Transaction } from "prosemirror-state"; import { EditorView } from "prosemirror-view"; import buildKeymap from "../../util/ProsemirrorKeymap"; import { inpRules } from "../../util/RichTextRules"; -import { schema } from "../../util/RichTextSchema"; +import { schema, ImageResizeView } from "../../util/RichTextSchema"; import { TooltipLinkingMenu } from "../../util/TooltipLinkingMenu"; import { TooltipTextMenu } from "../../util/TooltipTextMenu"; import { ContextMenu } from "../../views/ContextMenu"; @@ -24,8 +24,6 @@ import { StrCast, Cast, NumCast, BoolCast } from "../../../new_fields/Types"; import { RichTextField } from "../../../new_fields/RichTextField"; import { Id } from "../../../new_fields/RefField"; import { UndoManager } from "../../util/UndoManager"; -import { Transform } from "prosemirror-transform"; -import { Transform as MatrixTransform } from "../../util/Transform"; // FormattedTextBox: Displays an editable plain text node that maps to a specified Key of a Document // @@ -149,7 +147,10 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe if (this._proseRef.current) { this._editorView = new EditorView(this._proseRef.current, { state: field && field.Data ? EditorState.fromJSON(config, JSON.parse(field.Data)) : EditorState.create(config), - dispatchTransaction: this.dispatchTransaction + dispatchTransaction: this.dispatchTransaction, + nodeViews: { + image(node, view, getPos) { return new ImageResizeView(node, view, getPos) } + } }); let text = StrCast(this.props.Document.documentText); if (text.startsWith("@@@")) { @@ -228,19 +229,6 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe description: NumCast(this.props.Document.nativeWidth) ? "Unfreeze" : "Freeze", event: this.textCapability }); - - // ContextMenu.Instance.addItem({ - // description: "Submenu", - // items: [ - // { - // description: "item 1", event: - // }, - // { - // description: "item 2", event: - // } - // ] - // }) - // e.stopPropagation() } onPointerWheel = (e: React.WheelEvent): void => { -- cgit v1.2.3-70-g09d2 From 244d4d127e7e1a0faadbc5a8baed7922ef03522c Mon Sep 17 00:00:00 2001 From: bob Date: Thu, 9 May 2019 14:11:35 -0400 Subject: cleaned up textlinking a little. --- src/client/util/DragManager.ts | 13 ++-- src/client/util/SelectionManager.ts | 4 +- src/client/util/TooltipTextMenu.tsx | 25 +++--- src/client/views/DocumentDecorations.tsx | 8 +- src/client/views/MainOverlayTextBox.tsx | 30 ++++--- .../views/collections/CollectionSchemaView.tsx | 3 +- src/client/views/collections/CollectionSubView.tsx | 2 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 8 +- src/client/views/nodes/FieldView.tsx | 2 +- src/client/views/nodes/FormattedTextBox.tsx | 91 ++++++++++++++++++---- 10 files changed, 122 insertions(+), 64 deletions(-) (limited to 'src/client/views/nodes/FormattedTextBox.tsx') diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index fbf20e244..eaf851a75 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -1,11 +1,9 @@ -import { action } from "mobx"; +import { action, runInAction } from "mobx"; +import { Doc, DocListCast } from "../../new_fields/Doc"; +import { Cast } from "../../new_fields/Types"; import { emptyFunction } from "../../Utils"; import { CollectionDockingView } from "../views/collections/CollectionDockingView"; import * as globalCssVariables from "../views/globalCssVariables.scss"; -import { MainOverlayTextBox } from "../views/MainOverlayTextBox"; -import { Doc, DocListCast } from "../../new_fields/Doc"; -import { Cast } from "../../new_fields/Types"; -import { listSpec } from "../../new_fields/Schema"; export type dropActionType = "alias" | "copy" | undefined; export function SetupDrag(_reference: React.RefObject, docFunc: () => Doc, moveFunc?: DragManager.MoveFunction, dropAction?: dropActionType) { @@ -154,7 +152,10 @@ export namespace DragManager { [id: string]: any; } + export let StartDragFunctions: (() => void)[] = []; + export function StartDocumentDrag(eles: HTMLElement[], dragData: DocumentDragData, downX: number, downY: number, options?: DragOptions) { + runInAction(() => StartDragFunctions.map(func => func())); StartDrag(eles, dragData, downX, downY, options, (dropData: { [id: string]: any }) => (dropData.droppedDocuments = dragData.userDropAction == "alias" || (!dragData.userDropAction && dragData.dropAction == "alias") ? @@ -189,7 +190,6 @@ export namespace DragManager { dragDiv.style.pointerEvents = "none"; DragManager.Root().appendChild(dragDiv); } - if (!dragData.dontClearTextBox) MainOverlayTextBox.Instance.SetTextDoc(); let scaleXs: number[] = []; let scaleYs: number[] = []; @@ -217,6 +217,7 @@ export namespace DragManager { dragElement.style.top = "0"; dragElement.style.bottom = ""; dragElement.style.left = "0"; + dragElement.style.color = "black"; dragElement.style.transformOrigin = "0 0"; dragElement.style.zIndex = globalCssVariables.contextMenuZindex;// "1000"; dragElement.style.transform = `translate(${x}px, ${y}px) scale(${scaleX}, ${scaleY})`; diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts index fe5acf4b4..a3a8172c7 100644 --- a/src/client/util/SelectionManager.ts +++ b/src/client/util/SelectionManager.ts @@ -1,7 +1,7 @@ import { observable, action } from "mobx"; import { Doc } from "../../new_fields/Doc"; -import { MainOverlayTextBox } from "../views/MainOverlayTextBox"; import { DocumentView } from "../views/nodes/DocumentView"; +import { FormattedTextBox } from "../views/nodes/FormattedTextBox"; export namespace SelectionManager { class Manager { @@ -25,7 +25,7 @@ export namespace SelectionManager { DeselectAll(): void { manager.SelectedDocuments.map(dv => dv.props.whenActiveChanged(false)); manager.SelectedDocuments = []; - MainOverlayTextBox.Instance.SetTextDoc(); + FormattedTextBox.InputBoxOverlay = undefined; } @action ReselectAll() { diff --git a/src/client/util/TooltipTextMenu.tsx b/src/client/util/TooltipTextMenu.tsx index 15895fd1c..6eb654319 100644 --- a/src/client/util/TooltipTextMenu.tsx +++ b/src/client/util/TooltipTextMenu.tsx @@ -48,6 +48,7 @@ export class TooltipTextMenu { private fontSizeIndicator: HTMLSpanElement = document.createElement("span"); private linkEditor?: HTMLDivElement; private linkText?: HTMLDivElement; + private linkDrag?: HTMLImageElement; //dropdown doms private fontSizeDom?: Node; private fontStyleDom?: Node; @@ -168,8 +169,13 @@ export class TooltipTextMenu { this.linkText = document.createElement("div"); this.linkText.style.cssFloat = "left"; this.linkText.style.marginRight = "5px"; + this.linkText.style.marginLeft = "5px"; this.linkText.setAttribute("contenteditable", "true"); + this.linkText.style.whiteSpace = "nowrap"; + this.linkText.style.width = "150px"; + this.linkText.style.overflow = "hidden"; this.linkText.style.color = "white"; + this.linkText.onpointerdown = (e: PointerEvent) => { e.stopPropagation(); } let linkBtn = document.createElement("div"); linkBtn.textContent = ">>"; linkBtn.style.width = "20px"; @@ -196,16 +202,17 @@ export class TooltipTextMenu { e.preventDefault(); } } - let linkDrag = document.createElement("div"); - linkDrag.textContent = "O"; - linkDrag.style.width = "20px"; - linkDrag.style.height = "20px"; - linkDrag.style.color = "white"; - linkDrag.style.cssFloat = "left"; - linkDrag.onpointerdown = (e: PointerEvent) => { + this.linkDrag = document.createElement("img"); + this.linkDrag.src = "https://seogurusnyc.com/wp-content/uploads/2016/12/link-1.png"; + this.linkDrag.style.width = "20px"; + this.linkDrag.style.height = "20px"; + this.linkDrag.style.color = "white"; + this.linkDrag.style.background = "black"; + this.linkDrag.style.cssFloat = "left"; + this.linkDrag.onpointerdown = (e: PointerEvent) => { let dragData = new DragManager.LinkDragData(this.editorProps.Document); dragData.dontClearTextBox = true; - DragManager.StartLinkDrag(this.linkEditor!, dragData, e.clientX, e.clientY, + DragManager.StartLinkDrag(this.linkDrag!, dragData, e.clientX, e.clientY, { handlers: { dragComplete: action(() => { @@ -216,9 +223,9 @@ export class TooltipTextMenu { hideSource: false }) }; + this.linkEditor.appendChild(this.linkDrag); this.linkEditor.appendChild(this.linkText); this.linkEditor.appendChild(linkBtn); - this.linkEditor.appendChild(linkDrag) this.tooltip.appendChild(this.linkEditor); } diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index e3eb034fa..85ddadd64 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -5,7 +5,6 @@ import { DragLinksAsDocuments, DragManager } from "../util/DragManager"; import { SelectionManager } from "../util/SelectionManager"; import { undoBatch } from "../util/UndoManager"; import './DocumentDecorations.scss'; -import { MainOverlayTextBox } from "./MainOverlayTextBox"; import { DocumentView, PositionDocument } from "./nodes/DocumentView"; import { LinkMenu } from "./nodes/LinkMenu"; import { TemplateMenu } from "./TemplateMenu"; @@ -25,11 +24,9 @@ import { faLink } from '@fortawesome/free-solid-svg-icons'; import { library } from '@fortawesome/fontawesome-svg-core'; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { MINIMIZED_ICON_SIZE } from "../views/globalCssVariables.scss"; -import { CollectionFreeFormView } from "./collections/collectionFreeForm/CollectionFreeFormView"; import { CollectionView } from "./collections/CollectionView"; -import { createCipher } from "crypto"; -import { FieldView } from "./nodes/FieldView"; import { DocumentManager } from "../util/DocumentManager"; +import { FormattedTextBox } from "./nodes/FormattedTextBox"; library.add(faLink); @@ -328,6 +325,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> let selDoc = SelectionManager.SelectedDocuments()[0]; let container = selDoc.props.ContainingCollectionView ? selDoc.props.ContainingCollectionView.props.Document.proto : undefined; let dragData = new DragManager.LinkDragData(selDoc.props.Document, container ? [container] : []); + FormattedTextBox.InputBoxOverlay = undefined; DragManager.StartLinkDrag(this._linkerButton.current, dragData, e.pageX, e.pageY, { handlers: { dragComplete: action(emptyFunction), @@ -410,7 +408,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> break; } - MainOverlayTextBox.Instance.SetTextDoc(); + FormattedTextBox.InputBoxOverlay = undefined; SelectionManager.SelectedDocuments().forEach(element => { const rect = element.ContentDiv ? element.ContentDiv.getBoundingClientRect() : new DOMRect(); diff --git a/src/client/views/MainOverlayTextBox.tsx b/src/client/views/MainOverlayTextBox.tsx index 3b75c248a..91f626737 100644 --- a/src/client/views/MainOverlayTextBox.tsx +++ b/src/client/views/MainOverlayTextBox.tsx @@ -1,16 +1,12 @@ -import { action, observable, trace } from 'mobx'; +import { action, observable, reaction } from 'mobx'; import { observer } from 'mobx-react'; -import "normalize.css"; import * as React from 'react'; import { emptyFunction, returnTrue, returnZero } from '../../Utils'; -import '../northstar/model/ModelExtensions'; -import '../northstar/utils/Extensions'; import { DragManager } from '../util/DragManager'; import { Transform } from '../util/Transform'; +import "normalize.css"; import "./MainOverlayTextBox.scss"; import { FormattedTextBox } from './nodes/FormattedTextBox'; -import { Doc } from '../../new_fields/Doc'; -import { NumCast } from '../../new_fields/Types'; interface MainOverlayTextBoxProps { } @@ -18,8 +14,6 @@ interface MainOverlayTextBoxProps { @observer export class MainOverlayTextBox extends React.Component { public static Instance: MainOverlayTextBox; - @observable public TextDoc?: Doc = undefined; - public TextScroll: number = 0; @observable _textXf: () => Transform = () => Transform.Identity(); private _textFieldKey: string = "data"; private _textColor: string | null = null; @@ -30,15 +24,18 @@ export class MainOverlayTextBox extends React.Component super(props); this._textProxyDiv = React.createRef(); MainOverlayTextBox.Instance = this; + reaction(() => FormattedTextBox.InputBoxOverlay, + (box?: FormattedTextBox) => { + if (box) this.setTextDoc(box.props.fieldKey, box.CurrentDiv, box.props.ScreenToLocalTransform); + else this.setTextDoc(); + }); } @action - SetTextDoc(textDoc?: Doc, textFieldKey?: string, div?: HTMLDivElement, tx?: () => Transform) { + private setTextDoc(textFieldKey?: string, div?: HTMLDivElement, tx?: () => Transform) { if (this._textTargetDiv) { this._textTargetDiv.style.color = this._textColor; } - - this.TextDoc = textDoc; this._textFieldKey = textFieldKey!; this._textXf = tx ? tx : () => Transform.Identity(); this._textTargetDiv = div; @@ -46,15 +43,13 @@ export class MainOverlayTextBox extends React.Component if (div.parentElement && div.parentElement instanceof HTMLDivElement && div.parentElement.id === "screenSpace") this._textXf = () => Transform.Identity(); this._textColor = div.style.color; div.style.color = "transparent"; - this.TextScroll = div.scrollTop; } } @action textScroll = (e: React.UIEvent) => { if (this._textProxyDiv.current && this._textTargetDiv) { - this.TextScroll = (e as any)._targetInst.stateNode.scrollTop;// this._textProxyDiv.current.children[0].scrollTop; - this._textTargetDiv.scrollTop = this.TextScroll; + this._textTargetDiv.scrollTop = (e as any)._targetInst.stateNode.scrollTop; } } @@ -64,11 +59,12 @@ export class MainOverlayTextBox extends React.Component document.addEventListener('pointerup', this.textBoxUp); } } + @action textBoxMove = (e: PointerEvent) => { if (e.movementX > 1 || e.movementY > 1) { document.removeEventListener("pointermove", this.textBoxMove); document.removeEventListener('pointerup', this.textBoxUp); - let dragData = new DragManager.DocumentDragData([this.TextDoc!]); + let dragData = new DragManager.DocumentDragData(FormattedTextBox.InputBoxOverlay ? [FormattedTextBox.InputBoxOverlay.props.Document] : []); const [left, top] = this._textXf().inverse().transformPoint(0, 0); dragData.xOffset = e.clientX - left; dragData.yOffset = e.clientY - top; @@ -86,13 +82,13 @@ export class MainOverlayTextBox extends React.Component } render() { - if (this.TextDoc && this._textTargetDiv) { + if (FormattedTextBox.InputBoxOverlay && this._textTargetDiv) { let textRect = this._textTargetDiv.getBoundingClientRect(); let s = this._textXf().Scale; return
    -
    diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index 16818affd..6dd0e5935 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -322,8 +322,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { render() { library.add(faCog); library.add(faPlus); - //This can't just pass FieldValue to filter because filter passes other arguments to the passed in function, which end up as default values in FieldValue - const children = (this.children || []).filter(doc => FieldValue(doc)); + const children = this.children; return (
    this.onDrop(e, {})} ref={this.createTarget}> diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 828ac880a..082692d8d 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -50,7 +50,7 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T) { get children() { //TODO tfs: This might not be what we want? //This linter error can't be fixed because of how js arguments work, so don't switch this to filter(FieldValue) - return Cast(this.props.Document[this.props.fieldKey], listSpec(Doc), []).filter(doc => FieldValue(doc)); + return Cast(this.props.Document[this.props.fieldKey], listSpec(Doc), []).filter(doc => FieldValue(doc)).map(doc => doc as Doc); } @action diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 797f94d5f..c1d149098 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -70,7 +70,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { } public getActiveDocuments = () => { const curPage = FieldValue(this.Document.curPage, -1); - return FieldValue(this.children, [] as Doc[]).filter(doc => { + return this.children.filter(doc => { var page = NumCast(doc.page, -1); return page === curPage || page === -1; }); @@ -169,7 +169,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { // if (!this.props.active()) { // return; // } - let childSelected = (this.children || []).filter(doc => doc).some(doc => { + let childSelected = this.children.some(doc => { var dv = DocumentManager.Instance.getDocumentView(doc); return dv && SelectionManager.IsSelected(dv) ? true : false; }); @@ -222,7 +222,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { } bringToFront = (doc: Doc) => { - const docs = (this.children || []); + const docs = this.children; docs.slice().sort((doc1, doc2) => { if (doc1 === doc) return 1; if (doc2 === doc) return -1; @@ -268,7 +268,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { @computed.struct get views() { let curPage = FieldValue(this.Document.curPage, -1); - let docviews = (this.children || []).filter(doc => doc).reduce((prev, doc) => { + let docviews = this.children.reduce((prev, doc) => { if (!(doc instanceof Doc)) return prev; var page = NumCast(doc.page, -1); if (page === curPage || page === -1) { diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx index 613c24fa4..cdc1bdc85 100644 --- a/src/client/views/nodes/FieldView.tsx +++ b/src/client/views/nodes/FieldView.tsx @@ -1,6 +1,6 @@ import React = require("react"); import { observer } from "mobx-react"; -import { computed } from "mobx"; +import { computed, observable } from "mobx"; import { FormattedTextBox } from "./FormattedTextBox"; import { ImageBox } from "./ImageBox"; import { VideoBox } from "./VideoBox"; diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index 445a834ee..e7fb94777 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -1,29 +1,31 @@ -import { action, IReactionDisposer, reaction, trace, computed, _allowStateChangesInsideComputed } from "mobx"; +import { action, IReactionDisposer, observable, reaction } from "mobx"; +import { observer } from "mobx-react"; import { baseKeymap } from "prosemirror-commands"; import { history } from "prosemirror-history"; import { keymap } from "prosemirror-keymap"; import { EditorState, Plugin, Transaction } from "prosemirror-state"; import { EditorView } from "prosemirror-view"; +import { Doc, Field, HeightSym, Opt, WidthSym } from "../../../new_fields/Doc"; +import { RichTextField } from "../../../new_fields/RichTextField"; +import { createSchema, makeInterface } from "../../../new_fields/Schema"; +import { Cast, NumCast, StrCast } from "../../../new_fields/Types"; +import { DocServer } from "../../DocServer"; +import { DocumentManager } from "../../util/DocumentManager"; +import { DragManager } from "../../util/DragManager"; import buildKeymap from "../../util/ProsemirrorKeymap"; import { inpRules } from "../../util/RichTextRules"; -import { schema, ImageResizeView } from "../../util/RichTextSchema"; +import { ImageResizeView, schema } from "../../util/RichTextSchema"; +import { SelectionManager } from "../../util/SelectionManager"; import { TooltipLinkingMenu } from "../../util/TooltipLinkingMenu"; import { TooltipTextMenu } from "../../util/TooltipTextMenu"; +import { undoBatch, UndoManager } from "../../util/UndoManager"; import { ContextMenu } from "../../views/ContextMenu"; -import { MainOverlayTextBox } from "../MainOverlayTextBox"; +import { CollectionDockingView } from "../collections/CollectionDockingView"; +import { DocComponent } from "../DocComponent"; +import { InkingControl } from "../InkingControl"; import { FieldView, FieldViewProps } from "./FieldView"; import "./FormattedTextBox.scss"; import React = require("react"); -import { SelectionManager } from "../../util/SelectionManager"; -import { DocComponent } from "../DocComponent"; -import { createSchema, makeInterface } from "../../../new_fields/Schema"; -import { Opt, Doc, WidthSym, HeightSym } from "../../../new_fields/Doc"; -import { observer } from "mobx-react"; -import { InkingControl } from "../InkingControl"; -import { StrCast, Cast, NumCast, BoolCast } from "../../../new_fields/Types"; -import { RichTextField } from "../../../new_fields/RichTextField"; -import { Id } from "../../../new_fields/RefField"; -import { UndoManager } from "../../util/UndoManager"; // FormattedTextBox: Displays an editable plain text node that maps to a specified Key of a Document // @@ -62,15 +64,23 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe private _proseRef: React.RefObject; private _editorView: Opt; private _gotDown: boolean = false; + private _dropDisposer?: DragManager.DragDropDisposer; private _reactionDisposer: Opt; private _inputReactionDisposer: Opt; private _proxyReactionDisposer: Opt; + public get CurrentDiv(): HTMLDivElement { return this._ref.current!; } + + @observable public static InputBoxOverlay?: FormattedTextBox = undefined; + public static InputBoxOverlayScroll: number = 0; constructor(props: FieldViewProps) { super(props); this._ref = React.createRef(); this._proseRef = React.createRef(); + if (this.props.isOverlay) { + DragManager.StartDragFunctions.push(() => FormattedTextBox.InputBoxOverlay = undefined); + } } _applyingChange: boolean = false; @@ -94,7 +104,27 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe } } + @undoBatch + @action + drop = async (e: Event, de: DragManager.DropEvent) => { + if (de.data instanceof DragManager.LinkDragData) { + let sourceDoc = de.data.linkSourceDocument; + let destDoc = this.props.Document; + + const protoDest = destDoc.proto; + const protoSrc = sourceDoc.proto; + Doc.MakeLink(protoSrc ? protoSrc : sourceDoc, protoDest ? protoDest : destDoc); + de.data.droppedDocuments.push(destDoc); + e.stopPropagation(); + } + } + componentDidMount() { + if (this._ref.current) { + this._dropDisposer = DragManager.MakeDropTarget(this._ref.current, { + handlers: { drop: this.drop.bind(this) } + }); + } const config = { schema, inpRules, //these currently don't do anything, but could eventually be helpful @@ -117,7 +147,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe }; if (this.props.isOverlay) { - this._inputReactionDisposer = reaction(() => MainOverlayTextBox.Instance.TextDoc && MainOverlayTextBox.Instance.TextDoc[Id], + this._inputReactionDisposer = reaction(() => FormattedTextBox.InputBoxOverlay, () => { if (this._editorView) { this._editorView.destroy(); @@ -127,7 +157,12 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe ); } else { this._proxyReactionDisposer = reaction(() => this.props.isSelected(), - () => this.props.isSelected() && MainOverlayTextBox.Instance.SetTextDoc(this.props.Document, this.props.fieldKey, this._ref.current!, this.props.ScreenToLocalTransform)); + () => { + if (this.props.isSelected()) { + FormattedTextBox.InputBoxOverlay = this; + FormattedTextBox.InputBoxOverlayScroll = this._ref.current!.scrollTop; + } + }); } @@ -178,6 +213,9 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe if (this._proxyReactionDisposer) { this._proxyReactionDisposer(); } + if (this._dropDisposer) { + this._dropDisposer(); + } } onPointerDown = (e: React.PointerEvent): void => { @@ -186,6 +224,24 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe if (this._toolTipTextMenu && this._toolTipTextMenu.tooltip) this._toolTipTextMenu.tooltip.style.opacity = "0"; } + if (e.button === 0 && ((!this.props.isSelected() && !e.ctrlKey) || (this.props.isSelected() && e.ctrlKey)) && !e.metaKey) { + if (e.target && (e.target as any).href) { + let href = (e.target as any).href; + if (href.indexOf(DocServer.prepend("/doc/")) === 0) { + let docid = href.replace(DocServer.prepend("/doc/"), ""); + DocServer.GetRefField(docid).then(action((f: Opt) => { + if (f instanceof Doc) { + if (DocumentManager.Instance.getDocumentView(f)) + DocumentManager.Instance.getDocumentView(f)!.props.focus(f); + else CollectionDockingView.Instance.AddRightSplit(f); + } + })); + } + e.stopPropagation(); + e.preventDefault(); + } + + } if (e.button === 2 || (e.button === 0 && e.ctrlKey)) { this._gotDown = true; e.preventDefault(); @@ -199,12 +255,13 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe } } + @action onFocused = (e: React.FocusEvent): void => { if (!this.props.isOverlay) { - MainOverlayTextBox.Instance.SetTextDoc(this.props.Document, this.props.fieldKey, this._ref.current!, this.props.ScreenToLocalTransform); + FormattedTextBox.InputBoxOverlay = this; } else { if (this._proseRef.current) { - this._proseRef.current.scrollTop = MainOverlayTextBox.Instance.TextScroll; + this._proseRef.current.scrollTop = FormattedTextBox.InputBoxOverlayScroll; } } } -- cgit v1.2.3-70-g09d2 From 47424484409938367f47068274af4c0f51d4490c Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sun, 12 May 2019 20:24:26 -0400 Subject: fixed issues with scrolled text input. preview region for schema. and pasting in tables with ctrl-t. --- src/client/util/TooltipTextMenu.scss | 26 +++++++------- src/client/views/PreviewCursor.tsx | 9 ++++- .../views/collections/CollectionSchemaView.tsx | 2 +- .../collections/collectionFreeForm/MarqueeView.tsx | 40 ++++++++++++++++++++++ src/client/views/nodes/FormattedTextBox.scss | 3 +- src/client/views/nodes/FormattedTextBox.tsx | 4 +-- 6 files changed, 65 insertions(+), 19 deletions(-) (limited to 'src/client/views/nodes/FormattedTextBox.tsx') diff --git a/src/client/util/TooltipTextMenu.scss b/src/client/util/TooltipTextMenu.scss index 70d9ad772..437da0d63 100644 --- a/src/client/util/TooltipTextMenu.scss +++ b/src/client/util/TooltipTextMenu.scss @@ -162,19 +162,6 @@ .ProseMirror-icon span { vertical-align: text-top; } -.ProseMirror-example-setup-style hr { - padding: 2px 10px; - border: none; - margin: 1em 0; - } - - .ProseMirror-example-setup-style hr:after { - content: ""; - display: block; - height: 1px; - background-color: silver; - line-height: 2px; - } .ProseMirror ul, .ProseMirror ol { padding-left: 30px; @@ -255,6 +242,19 @@ -webkit-transform: translateX(-50%); transform: translateX(-50%); pointer-events: all; + .ProseMirror-example-setup-style hr { + padding: 2px 10px; + border: none; + margin: 1em 0; + } + + .ProseMirror-example-setup-style hr:after { + content: ""; + display: block; + height: 1px; + background-color: silver; + line-height: 2px; + } } .tooltipMenu:before { diff --git a/src/client/views/PreviewCursor.tsx b/src/client/views/PreviewCursor.tsx index 78024a58c..4218ea7c9 100644 --- a/src/client/views/PreviewCursor.tsx +++ b/src/client/views/PreviewCursor.tsx @@ -18,6 +18,13 @@ export class PreviewCursor extends React.Component<{}> { constructor(props: any) { super(props); document.addEventListener("keydown", this.onKeyPress); + document.addEventListener("paste", this.paste); + } + paste = (e: ClipboardEvent) => { + console.log(e.clipboardData); + console.log(e.clipboardData.getData("text/html")); + console.log(e.clipboardData.getData("text/csv")); + console.log(e.clipboardData.getData("text/plain")); } @action @@ -28,7 +35,7 @@ export class PreviewCursor extends React.Component<{}> { //if not these keys, make a textbox if preview cursor is active! if (e.key.startsWith("F") && !e.key.endsWith("F")) { } else if (e.key !== "Escape" && e.key !== "Alt" && e.key !== "Shift" && e.key !== "Meta" && e.key !== "Control" && !e.defaultPrevented && !(e as any).DASHFormattedTextBoxHandled) { - if ((!e.ctrlKey && !e.metaKey) || e.key === "v" || e.key === "q") { + if ((!e.ctrlKey && !e.metaKey) || (e.key >= "a" && e.key <= "z")) { PreviewCursor.Visible && PreviewCursor._onKeyPress && PreviewCursor._onKeyPress(e); PreviewCursor.Visible = false; } diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index 506e60a65..18319dc77 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -253,7 +253,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { get previewPanel() { // let doc = CompileScript(this.previewScript, { this: selected }, true)(); const previewDoc = this.previewDocument; - return !previewDoc ? (null) : ( + return !previewDoc || !this.previewRegionWidth ? (null) : (
    y += 40 * this.props.getTransform().Scale; }) })(); + } else if (e.key === "t" && e.ctrlKey) { + //heuristically converts pasted text into a table. + // assumes each entry is separated by a tab + // skips all rows until it gets to a row with more than one entry + // assumes that 1st row has header entry for each column + // assumes subsequent rows have entries for each column header OR + // any row that has only one column is a section header-- this header is then added as a column to subsequent rows until the next header + // assumes each cell is a string or a number + e.preventDefault(); + (async () => { + let text: string = await navigator.clipboard.readText(); + let ns = text.split("\n").filter(t => t.trim() != "\r" && t.trim() != ""); + while (ns.length > 0 && ns[0].split("\t").length < 2) + ns.splice(0, 1); + if (ns.length > 0) { + let columns = ns[0].split("\t"); + let docList: Doc[] = []; + let groupAttr: string | number = ""; + for (let i = 1; i < ns.length - 1; i++) { + let values = ns[i].split("\t"); + if (values.length === 1 && columns.length > 1) { + groupAttr = values[0]; + continue; + } + let doc = new Doc(); + columns.forEach((col, i) => { + console.log(values[i] + " " + Number(values[i]).toString()); + doc[columns[i]] = (values.length > i ? ((values[i].indexOf(Number(values[i]).toString()) !== -1) ? Number(values[i]) : values[i]) : undefined); + }); + if (groupAttr) { + doc["_group"] = groupAttr; + } + doc.title = i.toString(); + docList.push(doc); + } + let newCol = Docs.SchemaDocument(docList, { x: x, y: y, title: "-dropped table-", width: 300, height: 100 }); + newCol.proto!.schemaColumns = new List([...(groupAttr ? ["_group"] : []), ...columns.filter(c => c)]); + this.props.addDocument(newCol, false); + } + })(); } else { let newBox = Docs.TextDocument({ width: 200, height: 100, x: x, y: y, title: "-typed text-" }); this.props.addLiveTextDocument(newBox); diff --git a/src/client/views/nodes/FormattedTextBox.scss b/src/client/views/nodes/FormattedTextBox.scss index 458a62c5b..4a29c1949 100644 --- a/src/client/views/nodes/FormattedTextBox.scss +++ b/src/client/views/nodes/FormattedTextBox.scss @@ -19,7 +19,7 @@ box-sizing: border-box; background-color: inherit; border-style: solid; - overflow-y: scroll; + overflow-y: auto; overflow-x: hidden; color: initial; height: 100%; @@ -27,7 +27,6 @@ } .formattedTextBox-cont-hidden { - overflow: hidden; pointer-events: none; } .formattedTextBox-inner-rounded { diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index 37dc05ca5..7ebc31b0a 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -262,8 +262,8 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe if (!this.props.isOverlay) { FormattedTextBox.InputBoxOverlay = this; } else { - if (this._proseRef.current) { - this._proseRef.current.scrollTop = FormattedTextBox.InputBoxOverlayScroll; + if (this._ref.current) { + this._ref.current.scrollTop = FormattedTextBox.InputBoxOverlayScroll; } } } -- cgit v1.2.3-70-g09d2 From 4ed116991b86e4667fd78eb9ea034e3a9cc75a3e Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Wed, 15 May 2019 00:42:35 -0400 Subject: small fixes to start allowing trails of links. --- src/client/views/nodes/CollectionFreeFormDocumentView.tsx | 10 +++++----- src/client/views/nodes/DocumentView.tsx | 4 ++-- src/client/views/nodes/FormattedTextBox.tsx | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) (limited to 'src/client/views/nodes/FormattedTextBox.tsx') diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index 2d4900509..fc1dc2b1e 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -204,11 +204,11 @@ export class CollectionFreeFormDocumentView extends DocComponent l.linkedFrom as Doc) : []), - ...(linkedToDocs ? linkedToDocs.map(l => l.linkedTo as Doc) : [])]; - if (linkedDocs) { - DocumentManager.Instance.jumpToDocument(linkedDocs[0]); + let linkedFwdDocs = [ + linkedToDocs ? linkedToDocs[0].linkedTo as Doc : linkedFromDocs ? linkedFromDocs[0].linkedFrom as Doc : expandedDocs[0], + linkedFromDocs ? linkedFromDocs[0].linkedFrom as Doc : linkedToDocs ? linkedToDocs[0].linkedTo as Doc : expandedDocs[0]]; + if (linkedFwdDocs) { + DocumentManager.Instance.jumpToDocument(linkedFwdDocs[altKey ? 1 : 0]); } } } diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index c97bcbd94..b88d18046 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -221,8 +221,8 @@ export class DocumentView extends DocComponent(Docu let doc = this.props.Document.proto ? this.props.Document.proto : this.props.Document; doc.isButton = !BoolCast(doc.isButton, false); if (doc.isButton && !doc.nativeWidth) { - doc.nativeWidth = doc[WidthSym](); - doc.nativeHeight = doc[HeightSym](); + doc.nativeWidth = this.props.Document[WidthSym](); + doc.nativeHeight = this.props.Document[HeightSym](); } } fullScreenClicked = (e: React.MouseEvent): void => { diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index 7ebc31b0a..cb09ad42c 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -229,7 +229,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe if (e.target && (e.target as any).href) { let href = (e.target as any).href; if (href.indexOf(DocServer.prepend("/doc/")) === 0) { - let docid = href.replace(DocServer.prepend("/doc/"), ""); + let docid = href.replace(DocServer.prepend("/doc/"), "").split("%")[0]; DocServer.GetRefField(docid).then(action((f: Opt) => { if (f instanceof Doc) { if (DocumentManager.Instance.getDocumentView(f)) -- cgit v1.2.3-70-g09d2 From d79d721baa25947dfbbd17eda173835d9ae93fa6 Mon Sep 17 00:00:00 2001 From: bob Date: Wed, 15 May 2019 15:05:57 -0400 Subject: several smaller fixes. --- src/client/views/DocumentDecorations.tsx | 30 +++++++------ .../views/collections/ParentDocumentSelector.tsx | 2 +- .../collections/collectionFreeForm/MarqueeView.tsx | 17 ++----- .../views/nodes/CollectionFreeFormDocumentView.tsx | 52 ++++++++++++---------- src/client/views/nodes/DocumentView.tsx | 8 ++-- src/client/views/nodes/FormattedTextBox.tsx | 2 +- src/client/views/nodes/IconBox.scss | 4 +- src/client/views/nodes/IconBox.tsx | 27 ++++++++--- src/new_fields/List.ts | 10 +++++ 9 files changed, 87 insertions(+), 65 deletions(-) (limited to 'src/client/views/nodes/FormattedTextBox.tsx') diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 627bedde2..8d85f7e2c 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -252,18 +252,20 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> if (!this._removeIcon) { if (selectedDocs.length === 1) this.getIconDoc(selectedDocs[0]).then(icon => selectedDocs[0].props.toggleMinimized()); - else { - let docViews = SelectionManager.ViewsSortedVertically(); - let topDocView = docViews[0]; - let ind = topDocView.templates.indexOf(Templates.Bullet.Layout); - if (ind !== -1) { - topDocView.templates.splice(ind, 1); - topDocView.props.Document.subBulletDocs = undefined; - } else { - topDocView.addTemplate(Templates.Bullet); - topDocView.props.Document.subBulletDocs = new List(docViews.filter(v => v !== topDocView).map(v => v.props.Document)); + else + if (Math.abs(e.pageX - this._downX) < Utils.DRAG_THRESHOLD && + Math.abs(e.pageY - this._downY) < Utils.DRAG_THRESHOLD) { + let docViews = SelectionManager.ViewsSortedVertically(); + let topDocView = docViews[0]; + let ind = topDocView.templates.indexOf(Templates.Bullet.Layout); + if (ind !== -1) { + topDocView.templates.splice(ind, 1); + topDocView.props.Document.subBulletDocs = undefined; + } else { + topDocView.addTemplate(Templates.Bullet); + topDocView.props.Document.subBulletDocs = new List(docViews.filter(v => v !== topDocView).map(v => v.props.Document)); + } } - } } this._removeIcon = false; } @@ -275,9 +277,9 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> let doc = selected[0].props.Document; let iconDoc = Docs.IconDocument(layoutString); iconDoc.isButton = true; - iconDoc.title = selected.length > 1 ? "ICONset" : "ICON" + StrCast(doc.title); - iconDoc.labelField = this._fieldKey; - iconDoc[this._fieldKey] = selected.length > 1 ? "collection" : undefined; + iconDoc.proto!.title = selected.length > 1 ? "ICONset" : "ICON" + StrCast(doc.title); + iconDoc.labelField = selected.length > 1 ? undefined : this._fieldKey; + iconDoc.proto![this._fieldKey] = selected.length > 1 ? "collection" : undefined; iconDoc.isMinimized = false; iconDoc.width = Number(MINIMIZED_ICON_SIZE); iconDoc.height = Number(MINIMIZED_ICON_SIZE); diff --git a/src/client/views/collections/ParentDocumentSelector.tsx b/src/client/views/collections/ParentDocumentSelector.tsx index dd1516da7..52f7914f3 100644 --- a/src/client/views/collections/ParentDocumentSelector.tsx +++ b/src/client/views/collections/ParentDocumentSelector.tsx @@ -18,7 +18,7 @@ export class SelectorContextMenu extends React.Component<{ Document: Doc }> { } async fetchDocuments() { - const docs = await SearchUtil.Search(`data_l:${this.props.Document[Id]}`, true); + const docs = await SearchUtil.Search(`data_l:"${this.props.Document[Id]}"`, true); runInAction(() => this._docs = docs); } diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index be7cddca6..ae4852aa2 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -212,6 +212,8 @@ export class MarqueeView extends React.Component } if (e.key === "Backspace" || e.key === "Delete" || e.key === "d") { this._commandExecuted = true; + e.stopPropagation(); + (e as any).propagationIsStopped = true; this.marqueeSelect().map(d => this.props.removeDocument(d)); let ink = Cast(this.props.container.props.Document.ink, InkField); if (ink) { @@ -291,20 +293,7 @@ export class MarqueeView extends React.Component this.props.selectDocuments([newCollection]); } this.cleanupInteractions(false); - } else - if (e.key === "s") { - // this._commandExecuted = true; - // e.stopPropagation(); - // e.preventDefault(); - // let bounds = this.Bounds; - // let selected = this.marqueeSelect(); - // SelectionManager.DeselectAll(); - // let summary = Docs.TextDocument({ x: bounds.left + bounds.width + 25, y: bounds.top, width: 300, height: 100, backgroundColor: "yellow", title: "-summary-" }); - // this.props.addLiveTextDocument(summary); - // selected.forEach(select => Doc.MakeLink(summary.proto!, select.proto!)); - - // this.cleanupInteractions(false); - } + } } @action marqueeInkSelect(ink: Map) { diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index 925945b17..38ac5cb90 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -1,19 +1,19 @@ -import { computed, trace, action, reaction, IReactionDisposer } from "mobx"; +import { action, computed, IReactionDisposer, reaction } from "mobx"; import { observer } from "mobx-react"; +import { Doc, DocListCast, DocListCastAsync } from "../../../new_fields/Doc"; +import { List } from "../../../new_fields/List"; +import { createSchema, listSpec, makeInterface } from "../../../new_fields/Schema"; +import { BoolCast, Cast, FieldValue, NumCast } from "../../../new_fields/Types"; +import { OmitKeys, Utils } from "../../../Utils"; +import { DocumentManager } from "../../util/DocumentManager"; +import { SelectionManager } from "../../util/SelectionManager"; import { Transform } from "../../util/Transform"; +import { UndoManager } from "../../util/UndoManager"; +import { CollectionDockingView } from "../collections/CollectionDockingView"; +import { DocComponent } from "../DocComponent"; import { DocumentView, DocumentViewProps, positionSchema } from "./DocumentView"; import "./DocumentView.scss"; import React = require("react"); -import { DocComponent } from "../DocComponent"; -import { createSchema, makeInterface, listSpec } from "../../../new_fields/Schema"; -import { FieldValue, Cast, NumCast, BoolCast, StrCast } from "../../../new_fields/Types"; -import { OmitKeys, Utils } from "../../../Utils"; -import { SelectionManager } from "../../util/SelectionManager"; -import { Doc, DocListCastAsync, DocListCast, } from "../../../new_fields/Doc"; -import { List } from "../../../new_fields/List"; -import { CollectionDockingView } from "../collections/CollectionDockingView"; -import { UndoManager } from "../../util/UndoManager"; -import { DocumentManager } from "../../util/DocumentManager"; export interface CollectionFreeFormDocumentViewProps extends DocumentViewProps { } @@ -140,7 +140,7 @@ export class CollectionFreeFormDocumentView extends DocComponent { + maximizedDocs.map(maximizedDoc => { let iconAnimating = Cast(maximizedDoc.isIconAnimating, List); if (!iconAnimating || (Date.now() - iconAnimating[6] > 1000)) { if (isMinimized === undefined) { @@ -182,12 +182,16 @@ export class CollectionFreeFormDocumentView extends DocComponent(Docu this._reactionDisposer = reaction(() => [this.props.Document.maximizedDocs, this.props.Document.summaryDoc, this.props.Document.summaryDoc instanceof Doc ? this.props.Document.summaryDoc.title : ""], () => { let maxDoc = DocListCast(this.props.Document.maximizedDocs); - if (maxDoc && StrCast(this.props.Document.layout).indexOf("IconBox") !== -1) { - this.props.Document.title = (maxDoc && maxDoc.length === 1 ? maxDoc[0].title + ".icon" : ""); + if (maxDoc.length === 1 && StrCast(maxDoc[0].title).startsWith("-") && StrCast(this.props.Document.layout).indexOf("IconBox") !== -1) { + this.props.Document.proto!.title = maxDoc[0].title + ".icon"; } let sumDoc = Cast(this.props.Document.summaryDoc, Doc); if (sumDoc instanceof Doc) { @@ -332,8 +332,8 @@ export class DocumentView extends DocComponent(Docu render() { var scaling = this.props.ContentScaling(); - var nativeHeight = this.nativeHeight > 0 ? this.nativeHeight.toString() + "px" : "100%"; - var nativeWidth = this.nativeWidth > 0 ? this.nativeWidth.toString() + "px" : "100%"; + var nativeHeight = this.nativeHeight > 0 ? `${this.nativeHeight}px` : (StrCast(this.props.Document.layout).indexOf("IconBox") === -1 ? "100%" : "auto"); + var nativeWidth = this.nativeWidth > 0 ? `${this.nativeWidth}px` : "100%"; return (
    ) => { if (f instanceof Doc) { if (DocumentManager.Instance.getDocumentView(f)) diff --git a/src/client/views/nodes/IconBox.scss b/src/client/views/nodes/IconBox.scss index f6d9860a3..893dc2d36 100644 --- a/src/client/views/nodes/IconBox.scss +++ b/src/client/views/nodes/IconBox.scss @@ -4,13 +4,13 @@ position: inherit; left:0; top:0; - height: 100%; + height: auto; width: max-content; // overflow: hidden; pointer-events: all; svg { width: $MINIMIZED_ICON_SIZE !important; - height: 100%; + height: auto; background: white; } .iconBox-label { diff --git a/src/client/views/nodes/IconBox.tsx b/src/client/views/nodes/IconBox.tsx index 071930633..b42eb44a5 100644 --- a/src/client/views/nodes/IconBox.tsx +++ b/src/client/views/nodes/IconBox.tsx @@ -7,7 +7,7 @@ import { observer } from "mobx-react"; import { FieldView, FieldViewProps } from './FieldView'; import "./IconBox.scss"; import { Cast, StrCast, BoolCast } from "../../../new_fields/Types"; -import { Doc } from "../../../new_fields/Doc"; +import { Doc, DocListCast } from "../../../new_fields/Doc"; import { IconField } from "../../../new_fields/IconField"; import { ContextMenu } from "../ContextMenu"; import Measure from "react-measure"; @@ -41,25 +41,40 @@ export class IconBox extends React.Component { setLabelField = (e: React.MouseEvent): void => { this.props.Document.hideLabel = !BoolCast(this.props.Document.hideLabel); } + setUseOwnTitleField = (e: React.MouseEvent): void => { + this.props.Document.useOwnTitle = !BoolCast(this.props.Document.useTargetTitle); + } specificContextMenu = (e: React.MouseEvent): void => { ContextMenu.Instance.addItem({ - description: BoolCast(this.props.Document.hideLabel) ? "show label" : "hide label", + description: BoolCast(this.props.Document.hideLabel) ? "Show label with icon" : "Remove label from icon", event: this.setLabelField }); + let maxDocs = DocListCast(this.props.Document.maximizedDocs); + if (maxDocs.length === 1 && !BoolCast(this.props.Document.hideLabel)) { + ContextMenu.Instance.addItem({ + description: BoolCast(this.props.Document.useOwnTitle) ? "Use target title for label" : "Use own title label", + event: this.setUseOwnTitleField + }); + } } @observable _panelWidth: number = 0; @observable _panelHeight: number = 0; render() { let labelField = StrCast(this.props.Document.labelField); let hideLabel = BoolCast(this.props.Document.hideLabel); - let maxDoc = Cast(this.props.Document.maximizedDocs, listSpec(Doc), []); - let firstDoc = maxDoc && maxDoc.length > 0 && maxDoc[0] instanceof Doc ? maxDoc[0] as Doc : undefined; - let label = !hideLabel && firstDoc && labelField ? firstDoc[labelField] : ""; + let maxDocs = DocListCast(this.props.Document.maximizedDocs); + let firstDoc = maxDocs.length ? maxDocs[0] : undefined; + let label = hideLabel ? "" : (firstDoc && labelField && !BoolCast(this.props.Document.useOwnTitle, false) ? firstDoc[labelField] : this.props.Document.title); return (
    {this.minimizedIcon} - runInAction(() => { if (r.offset!.width || BoolCast(this.props.Document.hideLabel)) this.props.Document.nativeWidth = this.props.Document.width = (r.offset!.width + Number(MINIMIZED_ICON_SIZE)); })}> + runInAction(() => { + if (r.offset!.width || BoolCast(this.props.Document.hideLabel)) { + this.props.Document.nativeWidth = (r.offset!.width + Number(MINIMIZED_ICON_SIZE)); + if (this.props.Document.height === Number(MINIMIZED_ICON_SIZE)) this.props.Document.width = this.props.Document.nativeWidth; + } + })}> {({ measureRef }) => {label} } diff --git a/src/new_fields/List.ts b/src/new_fields/List.ts index 88a65eba4..70e36f911 100644 --- a/src/new_fields/List.ts +++ b/src/new_fields/List.ts @@ -230,6 +230,16 @@ class ListImpl extends ObjectField { const list = new Proxy(this, { set: setter, get: listGetter, + ownKeys: target => Object.keys(target.__fields), + getOwnPropertyDescriptor: (target, prop) => { + if (prop in target.__fields) { + return { + configurable: true,//TODO Should configurable be true? + enumerable: true, + }; + } + return Reflect.getOwnPropertyDescriptor(target, prop); + }, deleteProperty: deleteProperty, defineProperty: () => { throw new Error("Currently properties can't be defined on documents using Object.defineProperty"); }, }); -- cgit v1.2.3-70-g09d2 From 171f285b5e61d7a0591578f1499f81b779a3c340 Mon Sep 17 00:00:00 2001 From: bob Date: Thu, 16 May 2019 15:54:34 -0400 Subject: fixed ? pdf rendering. freezing text boxes. --- src/client/views/nodes/FormattedTextBox.tsx | 12 ++++++------ src/client/views/nodes/PDFBox.tsx | 25 +++++++++++++++---------- 2 files changed, 21 insertions(+), 16 deletions(-) (limited to 'src/client/views/nodes/FormattedTextBox.tsx') diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index 8e04071c7..f24d4ae88 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -269,14 +269,14 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe } //REPLACE THIS WITH CAPABILITIES SPECIFIC TO THIS TYPE OF NODE - textCapability = (e: React.MouseEvent): void => { + freezeNativeDimensions = (e: React.MouseEvent): void => { if (NumCast(this.props.Document.nativeWidth)) { - this.props.Document.nativeWidth = undefined; - this.props.Document.nativeHeight = undefined; + this.props.Document.proto!.nativeWidth = undefined; + this.props.Document.proto!.nativeHeight = undefined; } else { - this.props.Document.nativeWidth = this.props.Document[WidthSym](); - this.props.Document.nativeHeight = this.props.Document[HeightSym](); + this.props.Document.proto!.nativeWidth = this.props.Document[WidthSym](); + this.props.Document.proto!.nativeHeight = this.props.Document[HeightSym](); } } specificContextMenu = (e: React.MouseEvent): void => { @@ -286,7 +286,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe } ContextMenu.Instance.addItem({ description: NumCast(this.props.Document.nativeWidth) ? "Unfreeze" : "Freeze", - event: this.textCapability + event: this.freezeNativeDimensions }); } diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index 14fe2df80..f6328fa83 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -71,13 +71,14 @@ export class PDFBox extends DocComponent(PdfDocumen @computed private get thumbnailPage() { return NumCast(this.props.Document.thumbnailPage, -1); } componentDidMount() { + let wasSelected = false; this._reactionDisposer = reaction( - () => [SelectionManager.SelectedDocuments().slice()], + () => this.props.isSelected(), () => { - if (this.curPage > 0 && this.thumbnailPage > 0 && this.curPage !== this.thumbnailPage && !this.props.isSelected()) { + if (this.curPage > 0 && this.curPage !== this.thumbnailPage && wasSelected && !this.props.isSelected()) { this.saveThumbnail(); - this._interactive = true; } + wasSelected = this._interactive = this.props.isSelected(); }, { fireImmediately: true }); @@ -256,7 +257,7 @@ export class PDFBox extends DocComponent(PdfDocumen .catch(function (error: any) { console.error('oops, something went wrong!', error); }); - }, 250); + }, 1250); } @action @@ -283,24 +284,27 @@ export class PDFBox extends DocComponent(PdfDocumen } @computed get pdfPage() { - return ; + console.log(this.curPage); + return ; } @computed get pdfContent() { + trace(); let pdfUrl = Cast(this.props.Document[this.props.fieldKey], PdfField); if (!pdfUrl) { return

    No pdf url to render

    ; } - let body = NumCast(this.props.Document.nativeHeight) ? - this.pdfPage : + let pdfpage = this.pdfPage; + let body = this.Document.nativeHeight ? + pdfpage : {({ measureRef }) =>
    - {this.pdfPage} + {pdfpage}
    }
    ; - let xf = NumCast(this.Document.nativeHeight) / this.renderHeight; + let xf = (this.Document.nativeHeight || 0) / this.renderHeight; return
    {body} @@ -336,7 +340,8 @@ export class PDFBox extends DocComponent(PdfDocumen @action onKeyDown = (e: React.KeyboardEvent) => e.key === "Alt" && (this._alt = true); @action onKeyUp = (e: React.KeyboardEvent) => e.key === "Alt" && (this._alt = false); render() { - let classname = "pdfBox-cont"; // + (this.props.isSelected() && !InkingControl.Instance.selectedTool && !this._alt ? "-interactive" : ""); + trace(); + let classname = "pdfBox-cont" + (this.props.isSelected() && !InkingControl.Instance.selectedTool && !this._alt ? "-interactive" : ""); return (
    {this.pdfRenderer} -- cgit v1.2.3-70-g09d2 From b29a0d1cef60b55f609fcd94ad38232ae557e681 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Thu, 16 May 2019 18:32:57 -0400 Subject: Fixed linter errors --- src/client/goldenLayout.d.ts | 3 +++ src/client/northstar/dash-fields/HistogramField.ts | 2 +- src/client/northstar/model/ModelHelpers.ts | 9 +++---- src/client/util/DragManager.ts | 2 +- src/client/util/RichTextSchema.tsx | 16 +++++------ src/client/util/TooltipTextMenu.tsx | 13 ++++----- src/client/views/DocumentDecorations.tsx | 31 +++++++++++----------- src/client/views/PresentationView.tsx | 4 +-- src/client/views/TemplateMenu.tsx | 4 +-- .../views/collections/CollectionDockingView.tsx | 5 ++-- .../views/collections/CollectionSchemaView.tsx | 10 +++---- .../views/collections/CollectionTreeView.tsx | 9 ++++--- .../collections/collectionFreeForm/MarqueeView.tsx | 13 ++++----- .../views/nodes/CollectionFreeFormDocumentView.tsx | 2 +- src/client/views/nodes/DocumentView.tsx | 2 +- src/client/views/nodes/FormattedTextBox.tsx | 8 +++--- src/client/views/nodes/ImageBox.tsx | 2 +- src/client/views/nodes/KeyValueBox.tsx | 2 +- src/client/views/nodes/KeyValuePair.tsx | 3 ++- src/client/views/nodes/VideoBox.tsx | 22 +++++++-------- src/new_fields/CursorField.ts | 6 ++--- src/new_fields/Doc.ts | 4 +-- src/new_fields/ObjectField.ts | 2 +- .../authentication/models/current_user_utils.ts | 2 +- 24 files changed, 91 insertions(+), 85 deletions(-) create mode 100644 src/client/goldenLayout.d.ts (limited to 'src/client/views/nodes/FormattedTextBox.tsx') diff --git a/src/client/goldenLayout.d.ts b/src/client/goldenLayout.d.ts new file mode 100644 index 000000000..b50240563 --- /dev/null +++ b/src/client/goldenLayout.d.ts @@ -0,0 +1,3 @@ + +declare const GoldenLayout: any; +export = GoldenLayout; \ No newline at end of file diff --git a/src/client/northstar/dash-fields/HistogramField.ts b/src/client/northstar/dash-fields/HistogramField.ts index aabc77bb2..1ee2189b9 100644 --- a/src/client/northstar/dash-fields/HistogramField.ts +++ b/src/client/northstar/dash-fields/HistogramField.ts @@ -52,7 +52,7 @@ export class HistogramField extends ObjectField { [Copy]() { let y = this.HistoOp; - let z = this.HistoOp["Copy"]; + let z = this.HistoOp.Copy; return new HistogramField(HistogramOperation.Duplicate(this.HistoOp)); } } \ No newline at end of file diff --git a/src/client/northstar/model/ModelHelpers.ts b/src/client/northstar/model/ModelHelpers.ts index 80bb71224..88e6e72b8 100644 --- a/src/client/northstar/model/ModelHelpers.ts +++ b/src/client/northstar/model/ModelHelpers.ts @@ -32,12 +32,9 @@ export class ModelHelpers { public static GetAggregateParametersIndex(histogramResult: HistogramResult, aggParameters?: AggregateParameters): number { return Array.from(histogramResult.aggregateParameters!).findIndex((value, i, set) => { - if (set[i] instanceof CountAggregateParameters && value instanceof CountAggregateParameters) - return true; - if (set[i] instanceof MarginAggregateParameters && value instanceof MarginAggregateParameters) - return true; - if (set[i] instanceof SumAggregateParameters && value instanceof SumAggregateParameters) - return true; + if (set[i] instanceof CountAggregateParameters && value instanceof CountAggregateParameters) return true; + if (set[i] instanceof MarginAggregateParameters && value instanceof MarginAggregateParameters) return true; + if (set[i] instanceof SumAggregateParameters && value instanceof SumAggregateParameters) return true; return false; }); } diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 26da34e67..05eb5c38a 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -41,7 +41,7 @@ export function SetupDrag(_reference: React.RefObject, docFunc: () export async function DragLinksAsDocuments(dragEle: HTMLElement, x: number, y: number, sourceDoc: Doc) { let srcTarg = sourceDoc.proto; let draggedDocs: Doc[] = []; - let draggedFromDocs: Doc[] = [] + let draggedFromDocs: Doc[] = []; if (srcTarg) { let linkToDocs = await DocListCastAsync(srcTarg.linkedToDocs); let linkFromDocs = await DocListCastAsync(srcTarg.linkedFromDocs); diff --git a/src/client/util/RichTextSchema.tsx b/src/client/util/RichTextSchema.tsx index c0e6f7899..3e3e98206 100644 --- a/src/client/util/RichTextSchema.tsx +++ b/src/client/util/RichTextSchema.tsx @@ -97,13 +97,13 @@ export const nodes: { [index: string]: NodeSpec } = { title: dom.getAttribute("title"), alt: dom.getAttribute("alt"), width: Math.min(100, Number(dom.getAttribute("width"))), - } + }; } }], // TODO if we don't define toDom, something weird happens: dragging the image will not move it but clone it. Why? toDOM(node) { - const attrs = { style: `width: ${node.attrs.width}` } - return ["img", { ...node.attrs, ...attrs }] + const attrs = { style: `width: ${node.attrs.width}` }; + return ["img", { ...node.attrs, ...attrs }]; } }, @@ -375,7 +375,7 @@ export class ImageResizeView { const currentX = e.pageX; const diffInPx = currentX - startX; self._outer.style.width = `${startWidth + diffInPx}`; - } + }; const onpointerup = () => { document.removeEventListener("pointermove", onpointermove); @@ -384,11 +384,11 @@ export class ImageResizeView { view.state.tr.setNodeMarkup(getPos(), null, { src: node.attrs.src, width: self._outer.style.width }) .setSelection(view.state.selection)); - } + }; - document.addEventListener("pointermove", onpointermove) - document.addEventListener("pointerup", onpointerup) - } + document.addEventListener("pointermove", onpointermove); + document.addEventListener("pointerup", onpointerup); + }; this._outer.appendChild(this._handle); this._outer.appendChild(this._img); diff --git a/src/client/util/TooltipTextMenu.tsx b/src/client/util/TooltipTextMenu.tsx index 6eb654319..223921428 100644 --- a/src/client/util/TooltipTextMenu.tsx +++ b/src/client/util/TooltipTextMenu.tsx @@ -175,7 +175,7 @@ export class TooltipTextMenu { this.linkText.style.width = "150px"; this.linkText.style.overflow = "hidden"; this.linkText.style.color = "white"; - this.linkText.onpointerdown = (e: PointerEvent) => { e.stopPropagation(); } + this.linkText.onpointerdown = (e: PointerEvent) => { e.stopPropagation(); }; let linkBtn = document.createElement("div"); linkBtn.textContent = ">>"; linkBtn.style.width = "20px"; @@ -192,8 +192,9 @@ export class TooltipTextMenu { let docid = href.replace(DocServer.prepend("/doc/"), ""); DocServer.GetRefField(docid).then(action((f: Opt) => { if (f instanceof Doc) { - if (DocumentManager.Instance.getDocumentView(f)) + if (DocumentManager.Instance.getDocumentView(f)) { DocumentManager.Instance.getDocumentView(f)!.props.focus(f); + } else CollectionDockingView.Instance.AddRightSplit(f); } })); @@ -201,7 +202,7 @@ export class TooltipTextMenu { e.stopPropagation(); e.preventDefault(); } - } + }; this.linkDrag = document.createElement("img"); this.linkDrag.src = "https://seogurusnyc.com/wp-content/uploads/2016/12/link-1.png"; this.linkDrag.style.width = "20px"; @@ -216,12 +217,12 @@ export class TooltipTextMenu { { handlers: { dragComplete: action(() => { - let m = dragData.droppedDocuments as Doc[]; + let m = dragData.droppedDocuments; this.makeLink(DocServer.prepend("/doc/" + m[0][Id])); }), }, hideSource: false - }) + }); }; this.linkEditor.appendChild(this.linkDrag); this.linkEditor.appendChild(this.linkText); @@ -239,7 +240,7 @@ export class TooltipTextMenu { e.stopPropagation(); e.preventDefault(); } - } + }; this.tooltip.appendChild(this.linkEditor); } diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index b2c65a31f..7083b1003 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -250,22 +250,21 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> selectedDocs[0].props.removeDocument && selectedDocs[0].props.removeDocument(this._iconDoc); } if (!this._removeIcon) { - if (selectedDocs.length === 1) + if (selectedDocs.length === 1) { this.getIconDoc(selectedDocs[0]).then(icon => selectedDocs[0].props.toggleMinimized()); - else - if (Math.abs(e.pageX - this._downX) < Utils.DRAG_THRESHOLD && - Math.abs(e.pageY - this._downY) < Utils.DRAG_THRESHOLD) { - let docViews = SelectionManager.ViewsSortedVertically(); - let topDocView = docViews[0]; - let ind = topDocView.templates.indexOf(Templates.Bullet.Layout); - if (ind !== -1) { - topDocView.templates.splice(ind, 1); - topDocView.props.Document.subBulletDocs = undefined; - } else { - topDocView.addTemplate(Templates.Bullet); - topDocView.props.Document.subBulletDocs = new List(docViews.filter(v => v !== topDocView).map(v => v.props.Document.proto!)); - } + } else if (Math.abs(e.pageX - this._downX) < Utils.DRAG_THRESHOLD && + Math.abs(e.pageY - this._downY) < Utils.DRAG_THRESHOLD) { + let docViews = SelectionManager.ViewsSortedVertically(); + let topDocView = docViews[0]; + let ind = topDocView.templates.indexOf(Templates.Bullet.Layout); + if (ind !== -1) { + topDocView.templates.splice(ind, 1); + topDocView.props.Document.subBulletDocs = undefined; + } else { + topDocView.addTemplate(Templates.Bullet); + topDocView.props.Document.subBulletDocs = new List(docViews.filter(v => v !== topDocView).map(v => v.props.Document.proto!)); } + } } this._removeIcon = false; } @@ -537,9 +536,9 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> if (temp !== Templates.Bullet.Layout || i === 0) { res.push(temp); } - }) + }); } - return res + return res; }, [] as string[]); let checked = false; docTemps.forEach(temp => { diff --git a/src/client/views/PresentationView.tsx b/src/client/views/PresentationView.tsx index 098e725c7..7d0dc2913 100644 --- a/src/client/views/PresentationView.tsx +++ b/src/client/views/PresentationView.tsx @@ -1,7 +1,7 @@ import { observer } from "mobx-react"; -import React = require("react") +import React = require("react"); import { observable, action, runInAction, reaction } from "mobx"; -import "./PresentationView.scss" +import "./PresentationView.scss"; import "./Main.tsx"; import { DocumentManager } from "../util/DocumentManager"; import { Utils } from "../../Utils"; diff --git a/src/client/views/TemplateMenu.tsx b/src/client/views/TemplateMenu.tsx index cfe1b0663..e5b679e24 100644 --- a/src/client/views/TemplateMenu.tsx +++ b/src/client/views/TemplateMenu.tsx @@ -43,7 +43,7 @@ export class TemplateMenu extends React.Component { @action toggleTemplate = (event: React.ChangeEvent, template: Template): void => { if (event.target.checked) { - if (template.Name == "Bullet") { + if (template.Name === "Bullet") { let topDocView = this.props.docs[0]; topDocView.addTemplate(template); topDocView.props.Document.subBulletDocs = new List(this.props.docs.filter(v => v !== topDocView).map(v => v.props.Document.proto!)); @@ -52,7 +52,7 @@ export class TemplateMenu extends React.Component { } this.props.templates.set(template, true); } else { - if (template.Name == "Bullet") { + if (template.Name === "Bullet") { let topDocView = this.props.docs[0]; topDocView.removeTemplate(template); topDocView.props.Document.subBulletDocs = undefined; diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 58f1e33a1..deec64225 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -83,7 +83,7 @@ export class CollectionDockingView extends React.Component tab.config.component === "DocumentFrameRenderer").some((tab: any, j: number) => { if (Doc.AreProtosEqual(DocumentManager.Instance.getDocumentViewById(tab.config.props.documentId)!.Document, document)) { child.contentItems[j].remove(); @@ -94,8 +94,9 @@ export class CollectionDockingView extends React.Component doc) { let fieldContentView = ; let reference = React.createRef(); let onItemDown = (e: React.PointerEvent) => - (this.props.CollectionView!.props.isSelected() ? + (this.props.CollectionView.props.isSelected() ? SetupDrag(reference, () => props.Document, this.props.moveDocument)(e) : undefined); let applyToDoc = (doc: Doc, run: (args?: { [name: string]: any }) => any) => { const res = run({ this: doc }); @@ -127,7 +127,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { } const run = script.run; //TODO This should be able to be refactored to compile the script once - const val = await DocListCastAsync(this.props.Document[this.props.fieldKey]) + const val = await DocListCastAsync(this.props.Document[this.props.fieldKey]); val && val.forEach(doc => applyToDoc(doc, run)); }}> @@ -230,14 +230,14 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { DocListCast(this.props.Document.data).map(doc => { csv += self.columns.reduce((val, col) => val + (doc[col] ? doc[col]!.toString() : "") + ",", ""); csv = csv.substr(0, csv.length - 1) + "\n"; - }) + }); csv.substring(0, csv.length - 1); let dbName = StrCast(this.props.Document.title); let res = await Gateway.Instance.PostSchema(csv, dbName); if (self.props.CollectionView.props.addDocument) { let schemaDoc = await Docs.DBDocument("https://www.cs.brown.edu/" + dbName, { title: dbName }); if (schemaDoc) { - self.props.CollectionView.props.addDocument(schemaDoc, false); + self.props.CollectionView.props.addDocument(schemaDoc, false); } } } @@ -263,7 +263,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { get previewDocument(): Doc | undefined { const children = DocListCast(this.props.Document[this.props.fieldKey]); const selected = children.length > this._selectedIndex ? FieldValue(children[this._selectedIndex]) : undefined; - return selected ? (this.previewScript && this.previewScript != "this" ? FieldValue(Cast(selected[this.previewScript], Doc)) : selected) : undefined; + return selected ? (this.previewScript && this.previewScript !== "this" ? FieldValue(Cast(selected[this.previewScript], Doc)) : selected) : undefined; } get tableWidth() { return (this.props.PanelWidth() - 2 * this.borderWidth - this.DIVIDER_WIDTH) * (1 - this.splitPercentage / 100); } get previewRegionHeight() { return this.props.PanelHeight() - 2 * this.borderWidth; } diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 70c09d97c..6acef434e 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -56,7 +56,7 @@ class TreeView extends React.Component { } else { CollectionDockingView.Instance.AddRightSplit(this.props.document); } - }; + } get children() { return Cast(this.props.document.data, listSpec(Doc), []); // bcz: needed? .filter(doc => FieldValue(doc)); @@ -184,8 +184,9 @@ class TreeView extends React.Component { {TreeView.GetChildElements(doc instanceof Doc ? [doc] : docList, key !== "data", (doc: Doc) => this.remove(doc, key), this.move, this.props.dropAction)}
    ); - } else + } else { bulletType = BulletType.Collapsed; + } } }); return
    {
    ; } public static GetChildElements(docs: Doc[], allowMinimized: boolean, remove: ((doc: Doc) => void), move: DragManager.MoveFunction, dropAction: dropActionType) { - return docs.filter(child => child instanceof Doc && !child.excludeFromLibrary && (allowMinimized || !child.isMinimized)).filter(doc => FieldValue(doc)).map(child => - ); + return docs.filter(child => !child.excludeFromLibrary && (allowMinimized || !child.isMinimized)).map(child => + ); } } diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 12edb2c2a..c3c4115b8 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -63,7 +63,7 @@ export class MarqueeView extends React.Component e.preventDefault(); (async () => { let text: string = await navigator.clipboard.readText(); - let ns = text.split("\n").filter(t => t.trim() != "\r" && t.trim() != ""); + let ns = text.split("\n").filter(t => t.trim() !== "\r" && t.trim() !== ""); for (let i = 0; i < ns.length - 1; i++) { while (!(ns[i].trim() === "" || ns[i].endsWith("-\r") || ns[i].endsWith("-") || ns[i].endsWith(";\r") || ns[i].endsWith(";") || @@ -80,7 +80,7 @@ export class MarqueeView extends React.Component let newBox = Docs.TextDocument({ width: 200, height: 35, x: x + indent / 3 * 10, y: y, documentText: "@@@" + line, title: line }); this.props.addDocument(newBox, false); y += 40 * this.props.getTransform().Scale; - }) + }); })(); } else if (e.key === "b" && e.ctrlKey) { //heuristically converts pasted text into a table. @@ -93,9 +93,10 @@ export class MarqueeView extends React.Component e.preventDefault(); (async () => { let text: string = await navigator.clipboard.readText(); - let ns = text.split("\n").filter(t => t.trim() != "\r" && t.trim() != ""); - while (ns.length > 0 && ns[0].split("\t").length < 2) + let ns = text.split("\n").filter(t => t.trim() !== "\r" && t.trim() !== ""); + while (ns.length > 0 && ns[0].split("\t").length < 2) { ns.splice(0, 1); + } if (ns.length > 0) { let columns = ns[0].split("\t"); let docList: Doc[] = []; @@ -109,7 +110,7 @@ export class MarqueeView extends React.Component let doc = new Doc(); columns.forEach((col, i) => doc[columns[i]] = (values.length > i ? ((values[i].indexOf(Number(values[i]).toString()) !== -1) ? Number(values[i]) : values[i]) : undefined)); if (groupAttr) { - doc["_group"] = groupAttr; + doc._group = groupAttr; } doc.title = i.toString(); docList.push(doc); @@ -284,7 +285,7 @@ export class MarqueeView extends React.Component // summarizedDoc.isIconAnimating = new List([scrpt[0], scrpt[1], maxx, maxy, maxw, maxh, Date.now(), 0]); // }); this.props.addLiveTextDocument(summary); - }) + }); } else { this.props.addDocument(newCollection, false); diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index 7c7ca9e25..d4f660b3f 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -149,7 +149,7 @@ export class CollectionFreeFormDocumentView extends DocComponent([scrpt[0], scrpt[1], Date.now(), isMinimized ? 1 : 0]) + maximizedDoc.isIconAnimating = new List([scrpt[0], scrpt[1], Date.now(), isMinimized ? 1 : 0]); } } }); diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index cf8bcbb42..428dd9b36 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -244,7 +244,7 @@ export class DocumentView extends DocComponent(Docu const protoDest = destDoc.proto; const protoSrc = sourceDoc.proto; - if (de.mods == "Control") { + if (de.mods === "Control") { let src = protoSrc ? protoSrc : sourceDoc; let dst = protoDest ? protoDest : destDoc; dst.data = src; diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index f24d4ae88..f30022508 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -184,7 +184,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe state: field && field.Data ? EditorState.fromJSON(config, JSON.parse(field.Data)) : EditorState.create(config), dispatchTransaction: this.dispatchTransaction, nodeViews: { - image(node, view, getPos) { return new ImageResizeView(node, view, getPos) } + image(node, view, getPos) { return new ImageResizeView(node, view, getPos); } } }); let text = StrCast(this.props.Document.documentText); @@ -232,9 +232,11 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe let docid = href.replace(DocServer.prepend("/doc/"), "").split("?")[0]; DocServer.GetRefField(docid).then(action((f: Opt) => { if (f instanceof Doc) { - if (DocumentManager.Instance.getDocumentView(f)) + if (DocumentManager.Instance.getDocumentView(f)) { DocumentManager.Instance.getDocumentView(f)!.props.focus(f); - else CollectionDockingView.Instance.AddRightSplit(f); + } else { + CollectionDockingView.Instance.AddRightSplit(f); + } } })); } diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index 6472ae711..3cc60a6c5 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -165,7 +165,7 @@ export class ImageBox extends DocComponent(ImageD else if (field instanceof List) paths = field.filter(val => val instanceof ImageField).map(p => (p as ImageField).url.href); let nativeWidth = FieldValue(this.Document.nativeWidth, (this.props.PanelWidth as any) as string ? Number((this.props.PanelWidth as any) as string) : 50); let interactive = InkingControl.Instance.selectedTool ? "" : "-interactive"; - let id = this.props.id; // bcz: used to set id = "isExpander" in templates.tsx + let id = (this.props as any).id; // bcz: used to set id = "isExpander" in templates.tsx return (
    { @observable private _keyInput: string = ""; @observable private _valueInput: string = ""; @computed get splitPercentage() { return NumCast(this.props.Document.schemaSplitPercentage, 50); } - get fieldDocToLayout() { return this.props.fieldKey ? FieldValue(Cast(this.props.Document[this.props.fieldKey], Doc)) : this.props.Document } + get fieldDocToLayout() { return this.props.fieldKey ? FieldValue(Cast(this.props.Document[this.props.fieldKey], Doc)) : this.props.Document; } constructor(props: FieldViewProps) { super(props); diff --git a/src/client/views/nodes/KeyValuePair.tsx b/src/client/views/nodes/KeyValuePair.tsx index 5de660d57..4f7919f50 100644 --- a/src/client/views/nodes/KeyValuePair.tsx +++ b/src/client/views/nodes/KeyValuePair.tsx @@ -46,8 +46,9 @@ export class KeyValuePair extends React.Component {
    , + ,
    diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index d4f660b3f..001ce3095 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -205,11 +205,12 @@ export class CollectionFreeFormDocumentView extends DocComponent(Docu let sourceDoc = de.data.linkSourceDocument; let destDoc = this.props.Document; - const protoDest = destDoc.proto; - const protoSrc = sourceDoc.proto; - if (de.mods === "Control") { + if (de.mods === "AltKey") { + const protoDest = destDoc.proto; + const protoSrc = sourceDoc.proto; let src = protoSrc ? protoSrc : sourceDoc; let dst = protoDest ? protoDest : destDoc; - dst.data = src; + dst.data = (src.data! as ObjectField)[Copy](); dst.nativeWidth = src.nativeWidth; dst.nativeHeight = src.nativeHeight; } else { - Doc.MakeLink(protoSrc ? protoSrc : sourceDoc, protoDest ? protoDest : destDoc); + Doc.MakeLink(sourceDoc, destDoc); de.data.droppedDocuments.push(destDoc); } e.stopPropagation(); diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index f30022508..bf98fb40b 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -111,9 +111,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe let sourceDoc = de.data.linkSourceDocument; let destDoc = this.props.Document; - const protoDest = destDoc.proto; - const protoSrc = sourceDoc.proto; - Doc.MakeLink(protoSrc ? protoSrc : sourceDoc, protoDest ? protoDest : destDoc); + Doc.MakeLink(sourceDoc, destDoc); de.data.droppedDocuments.push(destDoc); e.stopPropagation(); } diff --git a/src/client/views/nodes/LinkBox.tsx b/src/client/views/nodes/LinkBox.tsx index 611cb66b6..68b692aad 100644 --- a/src/client/views/nodes/LinkBox.tsx +++ b/src/client/views/nodes/LinkBox.tsx @@ -31,7 +31,7 @@ export class LinkBox extends React.Component { @undoBatch onViewButtonPressed = async (e: React.PointerEvent): Promise => { e.stopPropagation(); - DocumentManager.Instance.jumpToDocument(this.props.pairedDoc); + DocumentManager.Instance.jumpToDocument(this.props.pairedDoc, e.altKey); } onEditButtonPressed = (e: React.PointerEvent): void => { diff --git a/src/client/views/nodes/LinkMenu.tsx b/src/client/views/nodes/LinkMenu.tsx index 11117122d..4cf798249 100644 --- a/src/client/views/nodes/LinkMenu.tsx +++ b/src/client/views/nodes/LinkMenu.tsx @@ -6,8 +6,7 @@ import { LinkEditor } from "./LinkEditor"; import './LinkMenu.scss'; import React = require("react"); import { Doc, DocListCast } from "../../../new_fields/Doc"; -import { Cast, FieldValue } from "../../../new_fields/Types"; -import { listSpec } from "../../../new_fields/Schema"; +import { Cast, FieldValue, StrCast } from "../../../new_fields/Types"; import { Id } from "../../../new_fields/RefField"; interface Props { @@ -24,7 +23,7 @@ export class LinkMenu extends React.Component { return links.map(link => { let doc = FieldValue(Cast(link[key], Doc)); if (doc) { - return this._editingLink = link)} type={type} />; + return this._editingLink = link)} type={type} />; } }); } diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index c898f697b..ad3b880cd 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -216,6 +216,8 @@ export namespace Doc { } export function MakeLink(source: Doc, target: Doc) { + let protoSrc = source.proto ? source.proto : source; + let protoTarg = target.proto ? target.proto : target; UndoManager.RunInBatch(() => { let linkDoc = Docs.TextDocument({ width: 100, height: 30, borderRounding: -1 }); //let linkDoc = new Doc; @@ -226,15 +228,15 @@ export namespace Doc { linkDoc.proto!.linkedTo = target; linkDoc.proto!.linkedFrom = source; - let linkedFrom = Cast(target.linkedFromDocs, listSpec(Doc)); + let linkedFrom = Cast(protoTarg.linkedFromDocs, listSpec(Doc)); if (!linkedFrom) { - target.linkedFromDocs = linkedFrom = new List(); + protoTarg.linkedFromDocs = linkedFrom = new List(); } linkedFrom.push(linkDoc); - let linkedTo = Cast(source.linkedToDocs, listSpec(Doc)); + let linkedTo = Cast(protoSrc.linkedToDocs, listSpec(Doc)); if (!linkedTo) { - source.linkedToDocs = linkedTo = new List(); + protoSrc.linkedToDocs = linkedTo = new List(); } linkedTo.push(linkDoc); return linkDoc; -- cgit v1.2.3-70-g09d2 From 3f12e4a4b776010e09d12a1adfb1d243675bcd6e Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Sun, 19 May 2019 01:15:22 -0400 Subject: Reorganized some stuff to hopefully make circular imports harder --- src/client/documents/Documents.ts | 33 ++++++++++++++++++++++ src/client/views/nodes/DocumentView.tsx | 4 +-- src/client/views/nodes/FormattedTextBox.tsx | 3 +- src/debug/Viewer.tsx | 44 ----------------------------- src/new_fields/Doc.ts | 31 -------------------- 5 files changed, 37 insertions(+), 78 deletions(-) (limited to 'src/client/views/nodes/FormattedTextBox.tsx') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index ed260d42e..0ebf6ff75 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -34,6 +34,7 @@ import { StrokeData, InkField } from "../../new_fields/InkField"; import { dropActionType } from "../util/DragManager"; import { DateField } from "../../new_fields/DateField"; import { schema } from "prosemirror-schema-basic"; +import { UndoManager } from "../util/UndoManager"; export interface DocumentOptions { x?: number; @@ -64,6 +65,38 @@ export interface DocumentOptions { } const delegateKeys = ["x", "y", "width", "height", "panX", "panY"]; +export namespace DocUtils { + export function MakeLink(source: Doc, target: Doc) { + let protoSrc = source.proto ? source.proto : source; + let protoTarg = target.proto ? target.proto : target; + UndoManager.RunInBatch(() => { + let linkDoc = Docs.TextDocument({ width: 100, height: 30, borderRounding: -1 }); + //let linkDoc = new Doc; + linkDoc.proto!.title = "-link name-"; + linkDoc.proto!.linkDescription = ""; + linkDoc.proto!.linkTags = "Default"; + + linkDoc.proto!.linkedTo = target; + linkDoc.proto!.linkedFrom = source; + + let linkedFrom = Cast(protoTarg.linkedFromDocs, listSpec(Doc)); + if (!linkedFrom) { + protoTarg.linkedFromDocs = linkedFrom = new List(); + } + linkedFrom.push(linkDoc); + + let linkedTo = Cast(protoSrc.linkedToDocs, listSpec(Doc)); + if (!linkedTo) { + protoSrc.linkedToDocs = linkedTo = new List(); + } + linkedTo.push(linkDoc); + return linkDoc; + }, "make link"); + } + + +} + export namespace Docs { let textProto: Doc; let histoProto: Doc; diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 760e31b49..ccf09f999 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -11,7 +11,7 @@ import { BoolCast, Cast, FieldValue, StrCast } from "../../../new_fields/Types"; import { CurrentUserUtils } from "../../../server/authentication/models/current_user_utils"; import { emptyFunction, Utils } from "../../../Utils"; import { DocServer } from "../../DocServer"; -import { Docs } from "../../documents/Documents"; +import { Docs, DocUtils } from "../../documents/Documents"; import { DocumentManager } from "../../util/DocumentManager"; import { DragManager, dropActionType } from "../../util/DragManager"; import { SearchUtil } from "../../util/SearchUtil"; @@ -264,7 +264,7 @@ export class DocumentView extends DocComponent(Docu dst.nativeHeight = src.nativeHeight; } else { - Doc.MakeLink(sourceDoc, destDoc); + DocUtils.MakeLink(sourceDoc, destDoc); de.data.droppedDocuments.push(destDoc); } e.stopPropagation(); diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index 98abde89e..d15813f9a 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -28,6 +28,7 @@ import { InkingControl } from "../InkingControl"; import { FieldView, FieldViewProps } from "./FieldView"; import "./FormattedTextBox.scss"; import React = require("react"); +import { DocUtils } from '../../documents/Documents'; library.add(faEdit); library.add(faSmile); @@ -116,7 +117,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe let sourceDoc = de.data.linkSourceDocument; let destDoc = this.props.Document; - Doc.MakeLink(sourceDoc, destDoc); + DocUtils.MakeLink(sourceDoc, destDoc); de.data.droppedDocuments.push(destDoc); e.stopPropagation(); } diff --git a/src/debug/Viewer.tsx b/src/debug/Viewer.tsx index d9b07aac6..720e1640a 100644 --- a/src/debug/Viewer.tsx +++ b/src/debug/Viewer.tsx @@ -3,56 +3,12 @@ import "normalize.css"; import * as React from 'react'; import * as ReactDOM from 'react-dom'; import { observer } from 'mobx-react'; -import { CurrentUserUtils } from '../server/authentication/models/current_user_utils'; -import { RouteStore } from '../server/RouteStore'; -import { emptyFunction } from '../Utils'; -import { Docs } from '../client/documents/Documents'; -import { SetupDrag } from '../client/util/DragManager'; -import { Transform } from '../client/util/Transform'; -import { UndoManager } from '../client/util/UndoManager'; -import { PresentationView } from '../client/views/PresentationView'; -import { CollectionDockingView } from '../client/views/collections/CollectionDockingView'; -import { ContextMenu } from '../client/views/ContextMenu'; -import { DocumentDecorations } from '../client/views/DocumentDecorations'; -import { InkingControl } from '../client/views/InkingControl'; -import { MainOverlayTextBox } from '../client/views/MainOverlayTextBox'; -import { DocumentView } from '../client/views/nodes/DocumentView'; -import { PreviewCursor } from '../client/views/PreviewCursor'; -import { SearchBox } from '../client/views/SearchBox'; -import { SelectionManager } from '../client/util/SelectionManager'; import { Doc, Field, FieldResult } from '../new_fields/Doc'; -import { Cast } from '../new_fields/Types'; import { DocServer } from '../client/DocServer'; -import { listSpec } from '../new_fields/Schema'; import { Id } from '../new_fields/RefField'; -import { HistoryUtil } from '../client/util/History'; import { List } from '../new_fields/List'; import { URLField } from '../new_fields/URLField'; -CurrentUserUtils; -RouteStore; -emptyFunction; -Docs; -SetupDrag; -Transform; -UndoManager; -PresentationView; -CollectionDockingView; -ContextMenu; -DocumentDecorations; -InkingControl; -MainOverlayTextBox; -DocumentView; -PreviewCursor; -SearchBox; -SelectionManager; -Doc; -Cast; -DocServer; -listSpec; -Id; -HistoryUtil; - configure({ enforceActions: "observed" }); diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index 020f764a2..c6fa31a99 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -4,12 +4,9 @@ import { autoObject, SerializationHelper, Deserializable } from "../client/util/ import { DocServer } from "../client/DocServer"; import { setter, getter, getField, updateFunction, deleteProperty } from "./util"; import { Cast, ToConstructor, PromiseValue, FieldValue, NumCast } from "./Types"; -import { UndoManager, undoBatch } from "../client/util/UndoManager"; import { listSpec } from "./Schema"; -import { List } from "./List"; import { ObjectField, Parent, OnUpdate } from "./ObjectField"; import { RefField, FieldId, Id, HandleUpdate } from "./RefField"; -import { Docs } from "../client/documents/Documents"; export function IsField(field: any): field is Field { return (typeof field === "string") @@ -221,34 +218,6 @@ export namespace Doc { return copy; } - export function MakeLink(source: Doc, target: Doc) { - let protoSrc = source.proto ? source.proto : source; - let protoTarg = target.proto ? target.proto : target; - UndoManager.RunInBatch(() => { - let linkDoc = Docs.TextDocument({ width: 100, height: 30, borderRounding: -1 }); - //let linkDoc = new Doc; - linkDoc.proto!.title = "-link name-"; - linkDoc.proto!.linkDescription = ""; - linkDoc.proto!.linkTags = "Default"; - - linkDoc.proto!.linkedTo = target; - linkDoc.proto!.linkedFrom = source; - - let linkedFrom = Cast(protoTarg.linkedFromDocs, listSpec(Doc)); - if (!linkedFrom) { - protoTarg.linkedFromDocs = linkedFrom = new List(); - } - linkedFrom.push(linkDoc); - - let linkedTo = Cast(protoSrc.linkedToDocs, listSpec(Doc)); - if (!linkedTo) { - protoSrc.linkedToDocs = linkedTo = new List(); - } - linkedTo.push(linkDoc); - return linkDoc; - }, "make link"); - } - export function MakeDelegate(doc: Doc): Doc; export function MakeDelegate(doc: Opt): Opt; export function MakeDelegate(doc: Opt): Opt { -- cgit v1.2.3-70-g09d2 From 060455feec89c94073636f612ccca54a0aaabb90 Mon Sep 17 00:00:00 2001 From: bob Date: Mon, 20 May 2019 21:29:17 -0400 Subject: fixed a few things for Firefox - dragging images, typing spaces, scrool speed. and focusing proeprly with zoomBasis. --- .vscode/launch.json | 9 +++++++++ .../collections/collectionFreeForm/CollectionFreeFormView.tsx | 9 +++------ src/client/views/nodes/CollectionFreeFormDocumentView.tsx | 3 +++ src/client/views/nodes/FormattedTextBox.tsx | 4 ++-- 4 files changed, 17 insertions(+), 8 deletions(-) (limited to 'src/client/views/nodes/FormattedTextBox.tsx') diff --git a/.vscode/launch.json b/.vscode/launch.json index d245be2ad..3b6549767 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -13,6 +13,15 @@ "url": "http://localhost:1050/login", "webRoot": "${workspaceFolder}", }, + { + "type": "firefox", + "request": "launch", + "name": "Launch Firefox against localhost", + "sourceMaps": "client", + "reAttach": true, + "url": "http://localhost:1050/login", + "webRoot": "${workspaceFolder}", + }, { "type": "chrome", "request": "launch", diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index ee6f4821f..3ec7184d2 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -183,7 +183,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { return; } e.stopPropagation(); - const coefficient = 1000; + const coefficient = 100; if (e.ctrlKey) { let deltaScale = (1 - (e.deltaY / coefficient)); @@ -215,7 +215,6 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { @action setPan(panX: number, panY: number) { - this.panDisposer && clearTimeout(this.panDisposer); this.props.Document.panTransformType = "None"; var scale = this.getLocalTransform().inverse().Scale; const newPanX = Math.min((1 - 1 / scale) * this.nativeWidth, Math.max(0, panX)); @@ -243,7 +242,6 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { doc.zIndex = docs.length + 1; } - panDisposer?: NodeJS.Timeout; focusDocument = (doc: Doc) => { const panX = this.Document.panX; const panY = this.Document.panY; @@ -265,15 +263,14 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { } } SelectionManager.DeselectAll(); - const newPanX = NumCast(doc.x) + NumCast(doc.width) / 2; - const newPanY = NumCast(doc.y) + NumCast(doc.height) / 2; + const newPanX = NumCast(doc.x) + NumCast(doc.width) / NumCast(doc.zoomBasis, 1) / 2; + const newPanY = NumCast(doc.y) + NumCast(doc.height) / NumCast(doc.zoomBasis, 1) / 2; const newState = HistoryUtil.getState(); newState.initializers[id] = { panX: newPanX, panY: newPanY }; HistoryUtil.pushState(newState); this.setPan(newPanX, newPanY); this.props.Document.panTransformType = "Ease"; this.props.focus(this.props.Document); - this.panDisposer = setTimeout(() => this.props.Document.panTransformType = "None", 2000); // wait 3 seconds, then reset to false } diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index fa2b09ba7..7c3180496 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -177,6 +177,9 @@ export class CollectionFreeFormDocumentView extends DocComponent { document.removeEventListener("pointerup", this.onPointerUp); diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index d15813f9a..5afef221c 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -366,7 +366,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe style={{ pointerEvents: interactive ? "all" : "none", }} - onKeyDown={this.onKeyPress} + // onKeyDown={this.onKeyPress} onKeyPress={this.onKeyPress} onFocus={this.onFocused} onClick={this.onClick} @@ -378,7 +378,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe // tfs: do we need this event handler onWheel={this.onPointerWheel} > -
    +
    ); } -- cgit v1.2.3-70-g09d2 From 732cc8c3aec072525535d246b1177181bbd3f7da Mon Sep 17 00:00:00 2001 From: bob Date: Wed, 29 May 2019 12:06:44 -0400 Subject: improved stacking view and captions templates. --- src/client/documents/Documents.ts | 6 +- src/client/views/MainOverlayTextBox.tsx | 7 +- src/client/views/Templates.tsx | 4 +- .../views/collections/CollectionStackingView.tsx | 125 ++++++++++++--------- src/client/views/collections/CollectionSubView.tsx | 2 +- .../views/nodes/CollectionFreeFormDocumentView.tsx | 6 +- src/client/views/nodes/DocumentContentsView.tsx | 1 + src/client/views/nodes/DocumentView.tsx | 5 + src/client/views/nodes/FormattedTextBox.tsx | 21 +++- 9 files changed, 107 insertions(+), 70 deletions(-) (limited to 'src/client/views/nodes/FormattedTextBox.tsx') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 4bc0df31f..9bf62196f 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -26,7 +26,7 @@ import { OmitKeys } from "../../Utils"; import { ImageField, VideoField, AudioField, PdfField, WebField } from "../../new_fields/URLField"; import { HtmlField } from "../../new_fields/HtmlField"; import { List } from "../../new_fields/List"; -import { Cast } from "../../new_fields/Types"; +import { Cast, NumCast } from "../../new_fields/Types"; import { IconField } from "../../new_fields/IconField"; import { listSpec } from "../../new_fields/Schema"; import { DocServer } from "../DocServer"; @@ -221,10 +221,12 @@ export namespace Docs { let inst = CreateInstance(imageProto, new ImageField(new URL(url)), options); requestImageSize(window.origin + RouteStore.corsProxy + "/" + url) .then((size: any) => { + let aspect = size.height / size.width; if (!inst.proto!.nativeWidth) { inst.proto!.nativeWidth = size.width; } - inst.proto!.nativeHeight = Number(inst.proto!.nativeWidth!) * size.height / size.width; + inst.proto!.nativeHeight = Number(inst.proto!.nativeWidth!) * aspect; + inst.proto!.height = NumCast(inst.proto!.width) * aspect; }) .catch((err: any) => console.log(err)); return inst; diff --git a/src/client/views/MainOverlayTextBox.tsx b/src/client/views/MainOverlayTextBox.tsx index 9be408049..6e8e6f8ce 100644 --- a/src/client/views/MainOverlayTextBox.tsx +++ b/src/client/views/MainOverlayTextBox.tsx @@ -17,6 +17,7 @@ export class MainOverlayTextBox extends React.Component @observable _textXf: () => Transform = () => Transform.Identity(); private _textFieldKey: string = "data"; private _textColor: string | null = null; + private _textHideOnLeave?: boolean; private _textTargetDiv: HTMLDivElement | undefined; private _textProxyDiv: React.RefObject; @@ -39,9 +40,9 @@ export class MainOverlayTextBox extends React.Component this._textFieldKey = textFieldKey!; this._textXf = tx ? tx : () => Transform.Identity(); this._textTargetDiv = div; + this._textHideOnLeave = FormattedTextBox.InputBoxOverlay && FormattedTextBox.InputBoxOverlay.props.hideOnLeave; if (div) { - if (div.parentElement && div.parentElement instanceof HTMLDivElement && div.parentElement.id === "screenSpace") this._textXf = () => Transform.Identity(); - this._textColor = div.style.color; + this._textColor = (getComputedStyle(div) as any).color; div.style.color = "transparent"; } } @@ -88,7 +89,7 @@ export class MainOverlayTextBox extends React.Component return
    -
    diff --git a/src/client/views/Templates.tsx b/src/client/views/Templates.tsx index 303f3f3b8..0cd367bcb 100644 --- a/src/client/views/Templates.tsx +++ b/src/client/views/Templates.tsx @@ -42,8 +42,8 @@ export namespace Templates { export const Caption = new Template("Caption", TemplatePosition.OutterBottom, `
    {layout}
    -
    - +
    +
    ` ); diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index a29648d5b..425eecebb 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -4,9 +4,9 @@ import { CollectionSubView, CollectionViewProps, SubCollectionViewProps } from " import { Doc, WidthSym, HeightSym, DocListCast } from "../../../new_fields/Doc"; import { DocumentView } from "../nodes/DocumentView"; import { Transform } from "../../util/Transform"; -import { emptyFunction, returnOne } from "../../../Utils"; +import { emptyFunction, returnOne, Utils } from "../../../Utils"; import "./CollectionStackingView.scss"; -import { action, reaction } from "mobx"; +import { action, reaction, trace, computed } from "mobx"; import { StrCast, NumCast } from "../../../new_fields/Types"; import { Id } from "../../../new_fields/FieldSymbols"; @@ -14,20 +14,13 @@ import { Id } from "../../../new_fields/FieldSymbols"; @observer export class CollectionStackingView extends CollectionSubView(doc => doc) { - getPreviewTransform = (): Transform => this.props.ScreenToLocalTransform(); + + get gridGap() { return 10; } + get gridSize() { return 20; } + get itemWidth() { return NumCast(this.props.Document.itemWidth, 250); } constructor(props: SubCollectionViewProps) { super(props); - // reaction(() => [this.props.PanelHeight() + this.props.PanelWidth(), - // (this.props.ContainingCollectionView && this.props.ContainingCollectionView.props.Document[this.props.ContainingCollectionView.props.fieldKey])], () => { - // if (this.props.ContainingCollectionView) { - // let allItems = DocListCast(this.props.ContainingCollectionView.props.Document[this.props.ContainingCollectionView.props.fieldKey]); - // for (let x = 0; x < allItems.length; x++) { - // resizeGridItem(allItems[x]); - // } - // } - // } - // ); } @action @@ -36,57 +29,79 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { addDocument(doc); return true; } + getDocTransform(doc: Doc, dref: HTMLDivElement) { + let { scale, translateX, translateY } = Utils.GetScreenTransform(dref); + let outerXf = Utils.GetScreenTransform(this.masonryGridRef!); + let offset = this.props.ScreenToLocalTransform().transformDirection(outerXf.translateX - translateX, outerXf.translateY - translateY); + return this.props.ScreenToLocalTransform().translate(offset[0], offset[1]).scale(NumCast(doc.width, 1) / this.itemWidth); + } + masonryGridRef: HTMLDivElement | null = null; + createRef = (ele: HTMLDivElement | null) => { + this.masonryGridRef = ele; + this.createDropTarget(ele!); + } + @computed + get children() { + return this.childDocs.map(d => { + let colSpan = Math.ceil((this.itemWidth + this.gridGap) / (this.gridSize + this.gridGap)); + let rowSpan = Math.ceil((this.itemWidth / d[WidthSym]() * d[HeightSym]() + this.gridGap) / (this.gridSize + this.gridGap)); + let dref = React.createRef(); + let dxf = () => this.getDocTransform(d, dref.current!); + return (
    + +
    ); + }) + } + onClick = (e: React.MouseEvent) => { + if (this.props.active()) { + let rect = (this.masonryGridRef!.firstChild! as HTMLElement).getBoundingClientRect(); + if (e.clientX < rect.left || e.clientX > rect.right || e.clientY > rect.bottom) this.props.select(false); + e.stopPropagation(); + } + } render() { - const docs = this.childDocs; - let gridGap = 10; - let gridSize = 20; - let itemWidth = NumCast(this.props.Document.itemWidth, 250); let leftMargin = 20; let topMargin = 20; - let itemCols = Math.ceil(itemWidth / (gridSize + gridGap)); - let cells = Math.floor((this.props.PanelWidth() - leftMargin) / (itemCols * (gridSize + gridGap))); + let itemCols = Math.ceil(this.itemWidth / (this.gridSize + this.gridGap)); + let cells = Math.floor((this.props.PanelWidth() - leftMargin) / (itemCols * (this.gridSize + this.gridGap))); return ( -
    e.stopPropagation()}> +
    e.stopPropagation()}>
    - {docs.map(d => { - let colSpan = Math.ceil((itemWidth + gridGap) / (gridSize + gridGap)); - let rowSpan = Math.ceil((itemWidth / d[WidthSym]() * d[HeightSym]() + gridGap) / (gridSize + gridGap)); - return (
    - -
    ); - })} + {this.children}
    ); diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index c4e72b23a..fe9e12640 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -212,7 +212,7 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T) { }).then(async (res: Response) => { (await res.json()).map(action((file: any) => { let path = window.location.origin + file; - let docPromise = this.getDocumentFromType(type, path, { ...options, nativeWidth: 600, width: 300, title: dropFileName }); + let docPromise = this.getDocumentFromType(type, path, { ...options, nativeWidth: 300, width: 300, title: dropFileName }); docPromise.then(doc => doc && this.props.addDocument(doc)); })); diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index 66d91f9c2..04e0a91f8 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -256,9 +256,6 @@ export class CollectionFreeFormDocumentView extends DocComponent { this.props.Document.libraryBrush = true; }; - onPointerLeave = (e: React.PointerEvent): void => { this.props.Document.libraryBrush = false; }; - borderRounding = () => { let br = NumCast(this.props.Document.borderRounding); return br >= 0 ? br : @@ -283,8 +280,7 @@ export class CollectionFreeFormDocumentView extends DocComponent boolean, select: (ctrl: boolean) => void, layoutKey: string, + hideOnLeave?: boolean }> { @computed get layout(): string { const layout = Cast(this.props.Document[this.props.layoutKey], "string"); diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 01c4d82fb..ed5862660 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -343,6 +343,9 @@ export class DocumentView extends DocComponent(Docu } } + onPointerEnter = (e: React.PointerEvent): void => { this.props.Document.libraryBrush = true; }; + onPointerLeave = (e: React.PointerEvent): void => { this.props.Document.libraryBrush = false; }; + isSelected = () => SelectionManager.IsSelected(this); select = (ctrlPressed: boolean) => SelectionManager.SelectDoc(this, ctrlPressed); @@ -366,6 +369,8 @@ export class DocumentView extends DocComponent(Docu transform: `scale(${scaling}, ${scaling})` }} onDrop={this.onDrop} onContextMenu={this.onContextMenu} onPointerDown={this.onPointerDown} onClick={this.onClick} + + onPointerEnter={this.onPointerEnter} onPointerLeave={this.onPointerLeave} > {this.contents}
    diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index 5afef221c..5b74c2e7e 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -50,8 +50,9 @@ library.add(faSmile); // this will edit the document and assign the new value to that field. //] -export interface FormattedTextBoxOverlay { +export interface FormattedTextBoxProps { isOverlay?: boolean; + hideOnLeave?: boolean; } const richTextSchema = createSchema({ @@ -62,7 +63,7 @@ type RichTextDocument = makeInterface<[typeof richTextSchema]>; const RichTextDocument = makeInterface(richTextSchema); @observer -export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTextBoxOverlay), RichTextDocument>(RichTextDocument) { +export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTextBoxProps), RichTextDocument>(RichTextDocument) { public static LayoutString(fieldStr: string = "data") { return FieldView.LayoutString(FormattedTextBox, fieldStr); } @@ -357,6 +358,17 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe this._undoTyping = UndoManager.StartBatch("undoTyping"); } } + + @observable + _entered = false; + @action + onPointerEnter = (e: React.PointerEvent) => { + this._entered = true; + } + @action + onPointerLeave = (e: React.PointerEvent) => { + this._entered = false; + } render() { let style = this.props.isOverlay ? "scroll" : "hidden"; let rounded = NumCast(this.props.Document.borderRounding) < 0 ? "-rounded" : ""; @@ -364,6 +376,9 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe return (
    -- cgit v1.2.3-70-g09d2 From 9dbf61fccc96f7c4d6bd63e25a7208b82df28705 Mon Sep 17 00:00:00 2001 From: bob Date: Wed, 29 May 2019 18:21:03 -0400 Subject: stacking view focus fixes. linkview fixes.- --- src/client/documents/Documents.ts | 3 ++- .../views/collections/CollectionStackingView.scss | 2 +- .../views/collections/CollectionStackingView.tsx | 10 ++++++++-- src/client/views/collections/CollectionView.tsx | 13 +++++++++++++ .../collectionFreeForm/CollectionFreeFormLinksView.tsx | 18 +++++++++++------- .../collections/collectionFreeForm/MarqueeView.tsx | 2 +- .../views/nodes/CollectionFreeFormDocumentView.tsx | 9 +-------- src/client/views/nodes/DocumentView.tsx | 6 ++++++ src/client/views/nodes/FormattedTextBox.tsx | 1 - 9 files changed, 43 insertions(+), 21 deletions(-) (limited to 'src/client/views/nodes/FormattedTextBox.tsx') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 9bf62196f..fffada459 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -36,6 +36,7 @@ import { DateField } from "../../new_fields/DateField"; import { UndoManager } from "../util/UndoManager"; import { RouteStore } from "../../server/RouteStore"; var requestImageSize = require('request-image-size'); +var path = require('path'); export interface DocumentOptions { x?: number; @@ -218,7 +219,7 @@ export namespace Docs { } export function ImageDocument(url: string, options: DocumentOptions = {}) { - let inst = CreateInstance(imageProto, new ImageField(new URL(url)), options); + let inst = CreateInstance(imageProto, new ImageField(new URL(url)), { title: path.basename(url), ...options }); requestImageSize(window.origin + RouteStore.corsProxy + "/" + url) .then((size: any) => { let aspect = size.height / size.width; diff --git a/src/client/views/collections/CollectionStackingView.scss b/src/client/views/collections/CollectionStackingView.scss index 6043a813d..0e4a8bb7e 100644 --- a/src/client/views/collections/CollectionStackingView.scss +++ b/src/client/views/collections/CollectionStackingView.scss @@ -8,7 +8,7 @@ width: 100%; height: 100%; position: absolute; - overflow-y: scroll; + overflow-y: auto; min-width: 250px; border-width: 0; box-shadow: $intermediate-color 0.2vw 0.2vw 0.8vw; diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 425eecebb..6d44aa37d 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -47,14 +47,20 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { let rowSpan = Math.ceil((this.itemWidth / d[WidthSym]() * d[HeightSym]() + this.gridGap) / (this.gridSize + this.gridGap)); let dref = React.createRef(); let dxf = () => this.getDocTransform(d, dref.current!); + let childFocus = (doc: Doc) => { + doc.libraryBrush = true; + this.props.focus(this.props.Document); // just focus on this collection, not the underlying document because the API doesn't support adding an offset to focus on and we can't pan zoom our contents to be centered. + } return (
    doc) { ContainingCollectionView={this.props.CollectionView} isTopMost={false} ScreenToLocalTransform={dxf} - focus={emptyFunction} + focus={childFocus} ContentScaling={returnOne} PanelWidth={d[WidthSym]} PanelHeight={d[HeightSym]} diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 39c8af4ab..a1e7c7c69 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -13,6 +13,8 @@ import { CollectionSchemaView } from "./CollectionSchemaView"; import { CollectionTreeView } from "./CollectionTreeView"; import { CollectionFreeFormView } from './collectionFreeForm/CollectionFreeFormView'; import { CollectionStackingView } from './CollectionStackingView'; +import { NumCast } from '../../../new_fields/Types'; +import { WidthSym, HeightSym } from '../../../new_fields/Doc'; export const COLLECTION_BORDER_WIDTH = 2; library.add(faTh); @@ -42,6 +44,16 @@ export class CollectionView extends React.Component { get isAnnotationOverlay() { return this.props.fieldKey && this.props.fieldKey === "annotations"; } // bcz: ? Why do we need to compare Id's? + freezeNativeDimensions = (e: React.MouseEvent): void => { + if (NumCast(this.props.Document.nativeWidth)) { + this.props.Document.proto!.nativeWidth = undefined; + this.props.Document.proto!.nativeHeight = undefined; + + } else { + this.props.Document.proto!.nativeWidth = this.props.Document[WidthSym](); + this.props.Document.proto!.nativeHeight = this.props.Document[HeightSym](); + } + } onContextMenu = (e: React.MouseEvent): void => { if (!this.isAnnotationOverlay && !e.isPropagationStopped() && this.props.Document[Id] !== CurrentUserUtils.MainDocId) { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7 ContextMenu.Instance.addItem({ description: "Freeform", event: undoBatch(() => this.props.Document.viewType = CollectionViewType.Freeform), icon: "signature" }); @@ -51,6 +63,7 @@ export class CollectionView extends React.Component { ContextMenu.Instance.addItem({ description: "Schema", event: undoBatch(() => this.props.Document.viewType = CollectionViewType.Schema), icon: "th-list" }); ContextMenu.Instance.addItem({ description: "Treeview", event: undoBatch(() => this.props.Document.viewType = CollectionViewType.Tree), icon: "tree" }); ContextMenu.Instance.addItem({ description: "Stacking", event: undoBatch(() => this.props.Document.viewType = CollectionViewType.Stacking), icon: "th-list" }); + ContextMenu.Instance.addItem({ description: NumCast(this.props.Document.nativeWidth) ? "Unfreeze" : "Freeze", event: this.freezeNativeDimensions, icon: "edit" }); } } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx index 85556fb90..6207dc8af 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx @@ -95,22 +95,26 @@ export class CollectionFreeFormLinksView extends React.Component { let srcViews = this.documentAnchors(connection.a); let targetViews = this.documentAnchors(connection.b); let possiblePairs: { a: Doc, b: Doc, }[] = []; srcViews.map(sv => targetViews.map(tv => possiblePairs.push({ a: sv.props.Document, b: tv.props.Document }))); - possiblePairs.map(possiblePair => - drawnPairs.reduce((found, drawnPair) => { - let match = (possiblePair.a === drawnPair.a && possiblePair.b === drawnPair.b); + possiblePairs.map(possiblePair => { + if (!drawnPairs.reduce((found, drawnPair) => { + let match1 = (Doc.AreProtosEqual(possiblePair.a, drawnPair.a) && Doc.AreProtosEqual(possiblePair.b, drawnPair.b)); + let match2 = (Doc.AreProtosEqual(possiblePair.a, drawnPair.b) && Doc.AreProtosEqual(possiblePair.b, drawnPair.a)); + let match = match1 || match2; if (match && !drawnPair.l.reduce((found, link) => found || link[Id] === connection.l[Id], false)) { drawnPair.l.push(connection.l); } return match || found; - }, false) - || - drawnPairs.push({ a: possiblePair.a, b: possiblePair.b, l: [connection.l] }) - ); + }, false)) { + console.log("A" + possiblePair.a[Id] + " B" + possiblePair.b[Id] + " L" + connection.l[Id]); + drawnPairs.push({ a: possiblePair.a, b: possiblePair.b, l: [connection.l] }) + } + }); return drawnPairs; }, [] as { a: Doc, b: Doc, l: Doc[] }[]); return connections.map(c => { diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 64d5301c9..14dbe1899 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -87,7 +87,7 @@ export class MarqueeView extends React.Component navigator.clipboard.readText().then(text => { let ns = text.split("\n").filter(t => t.trim() !== "\r" && t.trim() !== ""); if (ns.length === 1 && text.startsWith("http")) { - this.props.addDocument(Docs.ImageDocument(text, { width: 300, x: x, y: y }), false);// paste an image from its URL in the paste buffer + this.props.addDocument(Docs.ImageDocument(text, { nativeWidth: 300, width: 300, x: x, y: y }), false);// paste an image from its URL in the paste buffer } else { this.pasteTable(ns, x, y); } diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index 04e0a91f8..5f4d9e9ec 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -280,16 +280,9 @@ export class CollectionFreeFormDocumentView extends DocComponent(Docu
    { if (NumCast(this.props.Document.nativeWidth)) { this.props.Document.proto!.nativeWidth = undefined; -- cgit v1.2.3-70-g09d2 From 890a40ef8cc2efa7beea5722301b59ede5141238 Mon Sep 17 00:00:00 2001 From: bob Date: Thu, 30 May 2019 13:47:53 -0400 Subject: fixed context menus and tree view jitter. --- src/client/util/DragManager.ts | 4 +-- src/client/util/TooltipTextMenu.tsx | 2 +- src/client/views/ContextMenu.scss | 2 +- src/client/views/ContextMenuItem.tsx | 2 +- src/client/views/MainView.tsx | 6 ++-- .../views/collections/CollectionDockingView.tsx | 6 +++- .../views/collections/CollectionTreeView.scss | 6 +++- .../views/collections/CollectionTreeView.tsx | 33 +++++++++++++--------- src/client/views/collections/CollectionView.tsx | 30 +++++++------------- src/client/views/nodes/DocumentView.tsx | 31 ++++++++++++++------ src/client/views/nodes/FormattedTextBox.tsx | 25 +--------------- src/client/views/nodes/ImageBox.tsx | 11 ++++---- .../authentication/models/current_user_utils.ts | 20 ++++++------- 13 files changed, 85 insertions(+), 93 deletions(-) (limited to 'src/client/views/nodes/FormattedTextBox.tsx') diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 7f75a95f0..8f0cce095 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -26,7 +26,7 @@ export function SetupDrag(_reference: React.RefObject, docFunc: () // if (this.props.isSelected() || this.props.isTopMost) { if (e.button === 0) { e.stopPropagation(); - if (e.shiftKey) { + if (e.shiftKey && CollectionDockingView.Instance) { CollectionDockingView.Instance.StartOtherDrag([await docFunc()], e); } else { document.addEventListener("pointermove", onRowMove); @@ -264,7 +264,7 @@ export namespace DragManager { if (dragData instanceof DocumentDragData) { dragData.userDropAction = e.ctrlKey || e.altKey ? "alias" : undefined; } - if (e.shiftKey) { + if (e.shiftKey && CollectionDockingView.Instance) { AbortDrag(); CollectionDockingView.Instance.StartOtherDrag(docs, { pageX: e.pageX, diff --git a/src/client/util/TooltipTextMenu.tsx b/src/client/util/TooltipTextMenu.tsx index a1f80120f..5dd10f1bf 100644 --- a/src/client/util/TooltipTextMenu.tsx +++ b/src/client/util/TooltipTextMenu.tsx @@ -194,7 +194,7 @@ export class TooltipTextMenu { if (DocumentManager.Instance.getDocumentView(f)) { DocumentManager.Instance.getDocumentView(f)!.props.focus(f); } - else CollectionDockingView.Instance.AddRightSplit(f); + else if (CollectionDockingView.Instance) CollectionDockingView.Instance.AddRightSplit(f); } })); } diff --git a/src/client/views/ContextMenu.scss b/src/client/views/ContextMenu.scss index 61ae69179..74acba615 100644 --- a/src/client/views/ContextMenu.scss +++ b/src/client/views/ContextMenu.scss @@ -22,7 +22,7 @@ color: $light-color; } -.subMenu-cont { +.contextMenu-subMenu-cont { position: absolute; display: flex; z-index: 1000; diff --git a/src/client/views/ContextMenuItem.tsx b/src/client/views/ContextMenuItem.tsx index 63347e076..fcda0db89 100644 --- a/src/client/views/ContextMenuItem.tsx +++ b/src/client/views/ContextMenuItem.tsx @@ -56,7 +56,7 @@ export class ContextMenuItem extends React.Component { } else { let submenu = !this.overItem ? (null) : -
    +
    {this._items.map(prop => )}
    ; return ( diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 74dafadc4..a093ffdec 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -104,7 +104,9 @@ export class MainView extends React.Component { }, false); // drag event handler // click interactions for the context menu document.addEventListener("pointerdown", action(function (e: PointerEvent) { - if (!ContextMenu.Instance.intersects(e.pageX, e.pageY)) { + + const targets = document.elementsFromPoint(e.x, e.y); + if (targets && targets.length && targets[0].className.toString().indexOf("contextMenu") === -1) { ContextMenu.Instance.clearItems(); } }), true); @@ -163,7 +165,7 @@ export class MainView extends React.Component { } openNotifsCol = () => { - if (this._notifsCol) { + if (this._notifsCol && CollectionDockingView.Instance) { CollectionDockingView.Instance.AddRightSplit(this._notifsCol); } } diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index b6076b5f7..dcc1bd95d 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -22,6 +22,7 @@ import { ParentDocSelector } from './ParentDocumentSelector'; import { DocumentManager } from '../../util/DocumentManager'; import { CollectionViewType } from './CollectionBaseView'; import { Id } from '../../../new_fields/FieldSymbols'; +import { CurrentUserUtils } from '../../../server/authentication/models/current_user_utils'; @observer export class CollectionDockingView extends React.Component { @@ -415,7 +416,10 @@ export class DockedFrameRenderer extends React.Component { @observable private _panelHeight = 0; @observable private _document: Opt; get _stack(): any { - return (this.props as any).glContainer.parent.parent; + let parent = (this.props as any).glContainer.parent.parent; + if (this._document && this._document.excludeFromLibrary && parent.parent && parent.parent.contentItems.length > 1) + return parent.parent.contentItems[1]; + return parent; } constructor(props: any) { super(props); diff --git a/src/client/views/collections/CollectionTreeView.scss b/src/client/views/collections/CollectionTreeView.scss index 2f0329fc4..bb3be0a73 100644 --- a/src/client/views/collections/CollectionTreeView.scss +++ b/src/client/views/collections/CollectionTreeView.scss @@ -48,7 +48,11 @@ .treeViewItem-openRight { display: inline-block; // display: inline; - transform: translate(0px, -3px); //TODO Fix this + svg { + display:block; + padding:0px; + margin: 0px; + } } } diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 85aab96d3..2814c0502 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -9,7 +9,7 @@ import { CollectionSubView } from "./CollectionSubView"; import "./CollectionTreeView.scss"; import React = require("react"); import { Document, listSpec } from '../../../new_fields/Schema'; -import { Cast, StrCast, BoolCast, FieldValue } from '../../../new_fields/Types'; +import { Cast, StrCast, BoolCast, FieldValue, NumCast } from '../../../new_fields/Types'; import { Doc, DocListCast } from '../../../new_fields/Doc'; import { Id } from '../../../new_fields/FieldSymbols'; import { ContextMenu } from '../ContextMenu'; @@ -19,6 +19,7 @@ import { CollectionDockingView } from './CollectionDockingView'; import { DocumentManager } from '../../util/DocumentManager'; import { Docs } from '../../documents/Documents'; import { MainView } from '../MainView'; +import { CollectionViewType } from './CollectionBaseView'; export interface TreeViewProps { @@ -54,7 +55,7 @@ class TreeView extends React.Component { if (this.props.document.dockingConfig) { MainView.Instance.openWorkspace(this.props.document); } else { - CollectionDockingView.Instance.AddRightSplit(this.props.document); + this.props.addDocTab(this.props.document, "openRight"); } } @@ -122,11 +123,11 @@ class TreeView extends React.Component { return true; }} />); - let dataDocs = Cast(CollectionDockingView.Instance.props.Document.data, listSpec(Doc), []); + let dataDocs = CollectionDockingView.Instance ? Cast(CollectionDockingView.Instance.props.Document.data, listSpec(Doc), []) : []; let openRight = dataDocs && dataDocs.indexOf(this.props.document) !== -1 ? (null) : (
    - + {/* */}
    ); return (
    { } onWorkspaceContextMenu = (e: React.MouseEvent): void => { - if (!e.isPropagationStopped() && this.props.document[Id] !== CurrentUserUtils.MainDocId) { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7 + if (!e.isPropagationStopped()) { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7 ContextMenu.Instance.addItem({ description: "Open as Workspace", event: undoBatch(() => MainView.Instance.openWorkspace(this.props.document)) }); - ContextMenu.Instance.addItem({ description: "Open Right", event: () => this.props.addDocTab(this.props.document, "onRight") }); - ContextMenu.Instance.addItem({ description: "Open Fields", event: () => this.props.addDocTab(Docs.KVPDocument(this.props.document, { width: 300, height: 300 }), "onRight") }); - if (DocumentManager.Instance.getDocumentViews(this.props.document).length) { - ContextMenu.Instance.addItem({ description: "Focus", event: () => DocumentManager.Instance.getDocumentViews(this.props.document).map(view => view.props.focus(this.props.document)) }); + ContextMenu.Instance.addItem({ description: "Open Fields", event: () => this.props.addDocTab(Docs.KVPDocument(this.props.document, { width: 300, height: 300 }), "onRight"), icon: "layer-group" }); + if (NumCast(this.props.document.viewType) !== CollectionViewType.Docking) { + ContextMenu.Instance.addItem({ description: "Open Tab", event: () => this.props.addDocTab(this.props.document, "inTab"), icon: "folder" }); + ContextMenu.Instance.addItem({ description: "Open Right", event: () => this.props.addDocTab(this.props.document, "onRight"), icon: "caret-square-right" }); + if (DocumentManager.Instance.getDocumentViews(this.props.document).length) { + ContextMenu.Instance.addItem({ description: "Focus", event: () => DocumentManager.Instance.getDocumentViews(this.props.document).map(view => view.props.focus(this.props.document)) }); + } + ContextMenu.Instance.addItem({ description: "Delete Item", event: undoBatch(() => this.props.deleteDoc(this.props.document)) }); + } else { + ContextMenu.Instance.addItem({ description: "Delete Workspace", event: undoBatch(() => this.props.deleteDoc(this.props.document)) }); } - ContextMenu.Instance.addItem({ description: "Delete", event: undoBatch(() => this.props.deleteDoc(this.props.document)) }); ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15); e.stopPropagation(); } @@ -207,11 +213,10 @@ export class CollectionTreeView extends CollectionSubView(Document) { } } onContextMenu = (e: React.MouseEvent): void => { - if (!e.isPropagationStopped() && this.props.Document[Id] !== CurrentUserUtils.MainDocId) { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7 + // need to test if propagation has stopped because GoldenLayout forces a parallel react hierarchy to be created for its top-level layout + if (!e.isPropagationStopped() && this.props.Document.excludeFromLibrary) { // excludeFromLibrary means this is the user document ContextMenu.Instance.addItem({ description: "Create Workspace", event: undoBatch(() => MainView.Instance.createNewWorkspace()) }); - } - if (!ContextMenu.Instance.getItems().some(item => item.description === "Delete")) { - ContextMenu.Instance.addItem({ description: "Delete", event: undoBatch(() => this.remove(this.props.Document)) }); + ContextMenu.Instance.addItem({ description: "Delete Workspace", event: undoBatch(() => this.remove(this.props.Document)) }); } } render() { diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index a1e7c7c69..68eefab4c 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -1,20 +1,19 @@ import { library } from '@fortawesome/fontawesome-svg-core'; -import { faProjectDiagram, faSquare, faTh, faTree, faSignature, faThList } from '@fortawesome/free-solid-svg-icons'; +import { faProjectDiagram, faSignature, faSquare, faTh, faThList, faTree } from '@fortawesome/free-solid-svg-icons'; import { observer } from "mobx-react"; import * as React from 'react'; import { Id } from '../../../new_fields/FieldSymbols'; import { CurrentUserUtils } from '../../../server/authentication/models/current_user_utils'; import { undoBatch } from '../../util/UndoManager'; import { ContextMenu } from "../ContextMenu"; +import { ContextMenuProps } from '../ContextMenuItem'; import { FieldView, FieldViewProps } from '../nodes/FieldView'; import { CollectionBaseView, CollectionRenderProps, CollectionViewType } from './CollectionBaseView'; import { CollectionDockingView } from "./CollectionDockingView"; -import { CollectionSchemaView } from "./CollectionSchemaView"; -import { CollectionTreeView } from "./CollectionTreeView"; import { CollectionFreeFormView } from './collectionFreeForm/CollectionFreeFormView'; +import { CollectionSchemaView } from "./CollectionSchemaView"; import { CollectionStackingView } from './CollectionStackingView'; -import { NumCast } from '../../../new_fields/Types'; -import { WidthSym, HeightSym } from '../../../new_fields/Doc'; +import { CollectionTreeView } from "./CollectionTreeView"; export const COLLECTION_BORDER_WIDTH = 2; library.add(faTh); @@ -44,26 +43,17 @@ export class CollectionView extends React.Component { get isAnnotationOverlay() { return this.props.fieldKey && this.props.fieldKey === "annotations"; } // bcz: ? Why do we need to compare Id's? - freezeNativeDimensions = (e: React.MouseEvent): void => { - if (NumCast(this.props.Document.nativeWidth)) { - this.props.Document.proto!.nativeWidth = undefined; - this.props.Document.proto!.nativeHeight = undefined; - - } else { - this.props.Document.proto!.nativeWidth = this.props.Document[WidthSym](); - this.props.Document.proto!.nativeHeight = this.props.Document[HeightSym](); - } - } onContextMenu = (e: React.MouseEvent): void => { if (!this.isAnnotationOverlay && !e.isPropagationStopped() && this.props.Document[Id] !== CurrentUserUtils.MainDocId) { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7 - ContextMenu.Instance.addItem({ description: "Freeform", event: undoBatch(() => this.props.Document.viewType = CollectionViewType.Freeform), icon: "signature" }); + let subItems: ContextMenuProps[] = []; + subItems.push({ description: "Freeform", event: undoBatch(() => this.props.Document.viewType = CollectionViewType.Freeform), icon: "signature" }); if (CollectionBaseView.InSafeMode()) { ContextMenu.Instance.addItem({ description: "Test Freeform", event: undoBatch(() => this.props.Document.viewType = CollectionViewType.Invalid), icon: "project-diagram" }); } - ContextMenu.Instance.addItem({ description: "Schema", event: undoBatch(() => this.props.Document.viewType = CollectionViewType.Schema), icon: "th-list" }); - ContextMenu.Instance.addItem({ description: "Treeview", event: undoBatch(() => this.props.Document.viewType = CollectionViewType.Tree), icon: "tree" }); - ContextMenu.Instance.addItem({ description: "Stacking", event: undoBatch(() => this.props.Document.viewType = CollectionViewType.Stacking), icon: "th-list" }); - ContextMenu.Instance.addItem({ description: NumCast(this.props.Document.nativeWidth) ? "Unfreeze" : "Freeze", event: this.freezeNativeDimensions, icon: "edit" }); + subItems.push({ description: "Schema", event: undoBatch(() => this.props.Document.viewType = CollectionViewType.Schema), icon: "th-list" }); + subItems.push({ description: "Treeview", event: undoBatch(() => this.props.Document.viewType = CollectionViewType.Tree), icon: "tree" }); + subItems.push({ description: "Stacking", event: undoBatch(() => this.props.Document.viewType = CollectionViewType.Stacking), icon: "th-list" }); + ContextMenu.Instance.addItem({ description: "View Modes...", subitems: subItems }); } } diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index a16a52ac6..69691b6f3 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -29,6 +29,7 @@ import { DocumentContentsView } from "./DocumentContentsView"; import "./DocumentView.scss"; import React = require("react"); import { Id, Copy } from '../../../new_fields/FieldSymbols'; +import { ContextMenuProps } from '../ContextMenuItem'; const JsxParser = require('react-jsx-parser').default; //TODO Why does this need to be imported like this? library.add(faTrash); @@ -263,7 +264,7 @@ export class DocumentView extends DocComponent(Docu expandedProtoDocs.forEach(maxDoc => maxDoc.isMinimized = wasMinimized); } } - if (maxLocation && maxLocation !== "inPlace") { + if (maxLocation && maxLocation !== "inPlace" && CollectionDockingView.Instance) { let dataDocs = DocListCast(CollectionDockingView.Instance.props.Document.data); if (dataDocs) { expandedDocs.forEach(maxDoc => @@ -295,7 +296,7 @@ export class DocumentView extends DocComponent(Docu this._downX = e.clientX; this._downY = e.clientY; this._hitExpander = DocListCast(this.props.Document.subBulletDocs).length > 0; - if (e.shiftKey && e.buttons === 1) { + if (e.shiftKey && e.buttons === 1 && CollectionDockingView.Instance) { CollectionDockingView.Instance.StartOtherDrag([Doc.MakeAlias(this.props.Document)], e); e.stopPropagation(); } else { @@ -341,7 +342,7 @@ export class DocumentView extends DocComponent(Docu } } fullScreenClicked = (): void => { - CollectionDockingView.Instance.OpenFullScreen(Doc.MakeCopy(this.props.Document, false)); + CollectionDockingView.Instance && CollectionDockingView.Instance.OpenFullScreen(Doc.MakeCopy(this.props.Document, false)); SelectionManager.DeselectAll(); } @@ -398,6 +399,17 @@ export class DocumentView extends DocComponent(Docu this.templates = this.templates; } + freezeNativeDimensions = (e: React.MouseEvent): void => { + if (NumCast(this.props.Document.nativeWidth)) { + this.props.Document.proto!.nativeWidth = undefined; + this.props.Document.proto!.nativeHeight = undefined; + + } else { + this.props.Document.proto!.nativeWidth = this.props.Document[WidthSym](); + this.props.Document.proto!.nativeHeight = this.props.Document[HeightSym](); + } + } + @action onContextMenu = (e: React.MouseEvent): void => { e.stopPropagation(); @@ -409,16 +421,19 @@ export class DocumentView extends DocComponent(Docu e.preventDefault(); const cm = ContextMenu.Instance; - cm.addItem({ description: "Full Screen", event: this.fullScreenClicked, icon: "desktop" }); - cm.addItem({ description: "Open Tab", event: () => this.props.addDocTab && this.props.addDocTab(this.props.Document, "inTab"), icon: "folder" }); - cm.addItem({ description: "Open Right", event: () => CollectionDockingView.Instance.AddRightSplit(this.props.Document), icon: "caret-square-right" }); - cm.addItem({ description: "Fields", event: this.fieldsClicked, icon: "layer-group" }); + let subitems: ContextMenuProps[] = []; + subitems.push({ description: "Open Full Screen", event: this.fullScreenClicked, icon: "desktop" }); + subitems.push({ description: "Open Tab", event: () => this.props.addDocTab && this.props.addDocTab(this.props.Document, "inTab"), icon: "folder" }); + subitems.push({ description: "Open Right", event: () => this.props.addDocTab && this.props.addDocTab(this.props.Document, "onRight"), icon: "caret-square-right" }); + subitems.push({ description: "Open Fields", event: this.fieldsClicked, icon: "layer-group" }); + cm.addItem({ description: "Open...", subitems: subitems }); + cm.addItem({ description: NumCast(this.props.Document.nativeWidth) ? "Unfreeze" : "Freeze", event: this.freezeNativeDimensions, icon: "edit" }); cm.addItem({ description: "Pin to Pres", event: () => PresentationView.Instance.PinDoc(this.props.Document), icon: "map-pin" }); cm.addItem({ description: this.props.Document.isButton ? "Remove Button" : "Make Button", event: this.makeBtnClicked, icon: "concierge-bell" }); cm.addItem({ description: "Find aliases", event: async () => { const aliases = await SearchUtil.GetAliasesOfDocument(this.props.Document); - CollectionDockingView.Instance.AddRightSplit(Docs.SchemaDocument(["title"], aliases, {})); + this.props.addDocTab && this.props.addDocTab(Docs.SchemaDocument(["title"], aliases, {}), "onRight"); }, icon: "search" }); cm.addItem({ description: "Center View", event: () => this.props.focus(this.props.Document), icon: "crosshairs" }); diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index da584c811..5d93edaac 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -240,7 +240,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe if (DocumentManager.Instance.getDocumentView(f)) { DocumentManager.Instance.getDocumentView(f)!.props.focus(f); } else { - CollectionDockingView.Instance.AddRightSplit(f); + this.props.addDocTab && this.props.addDocTab(f, "onRight"); } } })); @@ -274,29 +274,6 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe } } } - - freezeNativeDimensions = (e: React.MouseEvent): void => { - if (NumCast(this.props.Document.nativeWidth)) { - this.props.Document.proto!.nativeWidth = undefined; - this.props.Document.proto!.nativeHeight = undefined; - - } else { - this.props.Document.proto!.nativeWidth = this.props.Document[WidthSym](); - this.props.Document.proto!.nativeHeight = this.props.Document[HeightSym](); - } - } - specificContextMenu = (e: React.MouseEvent): void => { - if (!this._gotDown) { - e.preventDefault(); - return; - } - ContextMenu.Instance.addItem({ - description: NumCast(this.props.Document.nativeWidth) ? "Unfreeze" : "Freeze", - event: this.freezeNativeDimensions, - icon: "edit" - }); - } - onPointerWheel = (e: React.WheelEvent): void => { if (this.props.isSelected()) { e.stopPropagation(); diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index 8ea6c5436..4c2b73b70 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -19,6 +19,7 @@ import { InkingControl } from '../InkingControl'; import { Doc, WidthSym, HeightSym } from '../../../new_fields/Doc'; import { faImage } from '@fortawesome/free-solid-svg-icons'; import { library } from '@fortawesome/fontawesome-svg-core'; +import { ContextMenuItemProps, ContextMenuProps } from '../ContextMenuItem'; var path = require('path'); @@ -131,12 +132,9 @@ export class ImageBox extends DocComponent(ImageD let field = Cast(this.Document[this.props.fieldKey], ImageField); if (field) { let url = field.url.href; - ContextMenu.Instance.addItem({ - description: "Copy path", event: () => { - Utils.CopyText(url); - }, icon: "expand-arrows-alt" - }); - ContextMenu.Instance.addItem({ + let subitems: ContextMenuProps[] = []; + subitems.push({ description: "Copy path", event: () => Utils.CopyText(url), icon: "expand-arrows-alt" }); + subitems.push({ description: "Rotate", event: action(() => { this.props.Document.rotation = (NumCast(this.props.Document.rotation) + 90) % 360; let nw = this.props.Document.nativeWidth; @@ -147,6 +145,7 @@ export class ImageBox extends DocComponent(ImageD this.props.Document.height = w; }), icon: "expand-arrows-alt" }); + ContextMenu.Instance.addItem({ description: "Image Funcs...", subitems: subitems }); } } diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index add347a88..e5b7a025b 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -1,21 +1,17 @@ -import { computed, observable, action, runInAction } from "mobx"; +import { action, computed, observable, runInAction } from "mobx"; import * as rp from 'request-promise'; +import { DocServer } from "../../../client/DocServer"; import { Docs } from "../../../client/documents/Documents"; -import { Attribute, AttributeGroup, Catalog, Schema, AggregateFunction } from "../../../client/northstar/model/idea/idea"; +import { Gateway, NorthstarSettings } from "../../../client/northstar/manager/Gateway"; +import { Attribute, AttributeGroup, Catalog, Schema } from "../../../client/northstar/model/idea/idea"; import { ArrayUtil } from "../../../client/northstar/utils/ArrayUtil"; -import { RouteStore } from "../../RouteStore"; -import { DocServer } from "../../../client/DocServer"; -import { Doc, Opt, Field } from "../../../new_fields/Doc"; -import { List } from "../../../new_fields/List"; import { CollectionViewType } from "../../../client/views/collections/CollectionBaseView"; -import { CollectionTreeView } from "../../../client/views/collections/CollectionTreeView"; import { CollectionView } from "../../../client/views/collections/CollectionView"; -import { NorthstarSettings, Gateway } from "../../../client/northstar/manager/Gateway"; -import { AttributeTransformationModel } from "../../../client/northstar/core/attribute/AttributeTransformationModel"; -import { ColumnAttributeModel } from "../../../client/northstar/core/attribute/AttributeModel"; -import { HistogramOperation } from "../../../client/northstar/operations/HistogramOperation"; -import { Cast, PromiseValue } from "../../../new_fields/Types"; +import { Doc } from "../../../new_fields/Doc"; +import { List } from "../../../new_fields/List"; import { listSpec } from "../../../new_fields/Schema"; +import { Cast } from "../../../new_fields/Types"; +import { RouteStore } from "../../RouteStore"; export class CurrentUserUtils { private static curr_email: string; -- cgit v1.2.3-70-g09d2 From d1b0f462ced168f3a9ac5d007ba1219e98a3b6cf Mon Sep 17 00:00:00 2001 From: bob Date: Fri, 31 May 2019 18:18:05 -0400 Subject: stacking views and more.. --- src/client/views/MainOverlayTextBox.tsx | 11 +++++++-- .../views/collections/CollectionBaseView.tsx | 2 +- .../views/collections/CollectionStackingView.scss | 2 +- .../views/collections/CollectionStackingView.tsx | 28 +++++++++++++++------- src/client/views/nodes/DocumentView.tsx | 2 +- src/client/views/nodes/FormattedTextBox.tsx | 13 ++++------ 6 files changed, 36 insertions(+), 22 deletions(-) (limited to 'src/client/views/nodes/FormattedTextBox.tsx') diff --git a/src/client/views/MainOverlayTextBox.tsx b/src/client/views/MainOverlayTextBox.tsx index 6e8e6f8ce..24327b995 100644 --- a/src/client/views/MainOverlayTextBox.tsx +++ b/src/client/views/MainOverlayTextBox.tsx @@ -7,6 +7,8 @@ import { Transform } from '../util/Transform'; import "normalize.css"; import "./MainOverlayTextBox.scss"; import { FormattedTextBox } from './nodes/FormattedTextBox'; +import { CollectionDockingView } from './collections/CollectionDockingView'; +import { Doc } from '../../new_fields/Doc'; interface MainOverlayTextBoxProps { } @@ -82,6 +84,11 @@ export class MainOverlayTextBox extends React.Component document.removeEventListener('pointerup', this.textBoxUp); } + addDocTab = (doc: Doc, location: string) => { + if (true) { // location === "onRight") { need to figure out stack to add "inTab" + CollectionDockingView.Instance.AddRightSplit(doc); + } + } render() { if (FormattedTextBox.InputBoxOverlay && this._textTargetDiv) { let textRect = this._textTargetDiv.getBoundingClientRect(); @@ -91,10 +98,10 @@ export class MainOverlayTextBox extends React.Component style={{ width: `${textRect.width * s}px`, height: `${textRect.height * s}px` }}> + ScreenToLocalTransform={this._textXf} PanelWidth={returnZero} PanelHeight={returnZero} focus={emptyFunction} addDocTab={this.addDocTab} />
    ; } - else return (null); + else return (null); Z } } \ No newline at end of file diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx index e89b8be0f..734669893 100644 --- a/src/client/views/collections/CollectionBaseView.tsx +++ b/src/client/views/collections/CollectionBaseView.tsx @@ -120,7 +120,7 @@ export class CollectionBaseView extends React.Component { // set the ZoomBasis only if hasn't already been set -- bcz: maybe set/resetting the ZoomBasis should be a parameter to addDocument? if (!alreadyAdded && (this.collectionViewType === CollectionViewType.Freeform || this.collectionViewType === CollectionViewType.Invalid)) { let zoom = NumCast(this.props.Document.scale, 1); - Doc.SetOnPrototype(doc, "zoomBasis", zoom); + // Doc.GetProto(doc).zoomBasis = zoom; } } return true; diff --git a/src/client/views/collections/CollectionStackingView.scss b/src/client/views/collections/CollectionStackingView.scss index 1bb0b2674..1ab335cc3 100644 --- a/src/client/views/collections/CollectionStackingView.scss +++ b/src/client/views/collections/CollectionStackingView.scss @@ -6,7 +6,7 @@ display: flex; flex-direction: column; width: 100%; - height: 100%; + height: auto; position: absolute; overflow-y: auto; border-width: 0; diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index bf246d4ec..a616b5ac7 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -1,24 +1,36 @@ import React = require("react"); +import { action, computed, IReactionDisposer, reaction } from "mobx"; import { observer } from "mobx-react"; -import { CollectionSubView, CollectionViewProps, SubCollectionViewProps } from "./CollectionSubView"; -import { Doc, WidthSym, HeightSym, DocListCast } from "../../../new_fields/Doc"; -import { DocumentView } from "../nodes/DocumentView"; -import { Transform } from "../../util/Transform"; +import { Doc, HeightSym, WidthSym } from "../../../new_fields/Doc"; +import { Id } from "../../../new_fields/FieldSymbols"; +import { NumCast } from "../../../new_fields/Types"; import { emptyFunction, returnOne, Utils } from "../../../Utils"; +import { DocumentView } from "../nodes/DocumentView"; import "./CollectionStackingView.scss"; -import { action, reaction, trace, computed } from "mobx"; -import { StrCast, NumCast } from "../../../new_fields/Types"; -import { Id } from "../../../new_fields/FieldSymbols"; +import { CollectionSubView } from "./CollectionSubView"; @observer export class CollectionStackingView extends CollectionSubView(doc => doc) { _masonryGridRef: HTMLDivElement | null = null; + _heightDisposer?: IReactionDisposer; get gridGap() { return 10; } get gridSize() { return 20; } get itemWidth() { return NumCast(this.props.Document.itemWidth, 250); } + componentDidMount() { + this._heightDisposer = reaction(() => [this.childDocs.map(d => d[HeightSym]()), this.props.PanelWidth()], + () => { + let hgt = (this.props.PanelWidth() > 500) ? this.props.Document[HeightSym]() : + this.childDocs.filter(d => !d.isMinimized).reduce((height, d) => height + d[HeightSym]() + this.gridGap, this.gridGap + 20 /* top margin */); + this.props.Document.height = hgt; + }, { fireImmediately: true }); + } + componentWillUnmount() { + if (this._heightDisposer) this._heightDisposer(); + } + @action moveDocument = (doc: Doc, targetCollection: Doc, addDocument: (document: Doc) => boolean): boolean => { this.props.removeDocument(doc); @@ -37,7 +49,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { } @computed get children() { - return this.childDocs.map(d => { + return this.childDocs.filter(d => !d.isMinimized).map(d => { let colSpan = Math.ceil((this.itemWidth + this.gridGap) / (this.gridSize + this.gridGap)); let rowSpan = Math.ceil((this.itemWidth / d[WidthSym]() * d[HeightSym]() + this.gridGap) / (this.gridSize + this.gridGap)); let dref = React.createRef(); diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 69691b6f3..f3a596558 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -328,7 +328,7 @@ export class DocumentView extends DocComponent(Docu } deleteClicked = (): void => { this.props.removeDocument && this.props.removeDocument(this.props.Document); } - fieldsClicked = (): void => { this.props.addDocTab(Docs.KVPDocument(this.Document, { width: 300, height: 300 }), "onRight") }; + fieldsClicked = (): void => { this.props.addDocTab(Docs.KVPDocument(this.props.Document, { width: 300, height: 300 }), "onRight") }; makeBtnClicked = (): void => { let doc = Doc.GetProto(this.props.Document); doc.isButton = !BoolCast(doc.isButton, false); diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index 5d93edaac..3b61c68dd 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -230,20 +230,15 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe this._toolTipTextMenu.tooltip.style.opacity = "0"; } } + let ctrlKey = e.ctrlKey; if (e.button === 0 && ((!this.props.isSelected() && !e.ctrlKey) || (this.props.isSelected() && e.ctrlKey)) && !e.metaKey) { if (e.target && (e.target as any).href) { let href = (e.target as any).href; if (href.indexOf(DocServer.prepend("/doc/")) === 0) { let docid = href.replace(DocServer.prepend("/doc/"), "").split("?")[0]; - DocServer.GetRefField(docid).then(action((f: Opt) => { - if (f instanceof Doc) { - if (DocumentManager.Instance.getDocumentView(f)) { - DocumentManager.Instance.getDocumentView(f)!.props.focus(f); - } else { - this.props.addDocTab && this.props.addDocTab(f, "onRight"); - } - } - })); + DocServer.GetRefField(docid).then(f => { + (f instanceof Doc) && DocumentManager.Instance.jumpToDocument(f, ctrlKey, document => this.props.addDocTab(document, "inTab")) + }); } e.stopPropagation(); e.preventDefault(); -- cgit v1.2.3-70-g09d2 From eccf79cb6e7abe2dd0555054e57d5037465c0bd2 Mon Sep 17 00:00:00 2001 From: bob Date: Tue, 4 Jun 2019 09:06:33 -0400 Subject: fix for stackingview with zoombasis. fix for text box links w/ styles --- src/client/views/collections/CollectionStackingView.tsx | 2 +- src/client/views/nodes/FormattedTextBox.tsx | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) (limited to 'src/client/views/nodes/FormattedTextBox.tsx') diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index ea3c144f2..acd585268 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -32,7 +32,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { let nh = NumCast(d.nativeHeight); if (nw && nh) hgt = nh / nw * Math.min(this.columnWidth, wid); return height + hgt + 2 * this.gridGap; - }, this.gridGap * 2); + }, this.gridGap * 2) * NumCast(this.props.Document.zoomBasis, 1); } }, { fireImmediately: true }); } diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index 3b61c68dd..5c635cc0c 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -231,9 +231,12 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe } } let ctrlKey = e.ctrlKey; - if (e.button === 0 && ((!this.props.isSelected() && !e.ctrlKey) || (this.props.isSelected() && e.ctrlKey)) && !e.metaKey) { - if (e.target && (e.target as any).href) { - let href = (e.target as any).href; + if (e.button === 0 && ((!this.props.isSelected() && !e.ctrlKey) || (this.props.isSelected() && e.ctrlKey)) && !e.metaKey && e.target) { + let href = (e.target as any).href; + for (let parent = (e.target as any).parentNode; !href && parent; parent = parent.parentNode) { + href = parent.childNodes[0].href; + } + if (href) { if (href.indexOf(DocServer.prepend("/doc/")) === 0) { let docid = href.replace(DocServer.prepend("/doc/"), "").split("?")[0]; DocServer.GetRefField(docid).then(f => { -- cgit v1.2.3-70-g09d2