aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--package-lock.json84
-rw-r--r--src/client/views/collections/CollectionView.tsx32
-rw-r--r--src/client/views/collections/CollectionViewChromes.tsx39
-rw-r--r--src/client/views/collections/collectionGrid/CollectionGridView.scss6
-rw-r--r--src/client/views/collections/collectionGrid/CollectionGridView.tsx407
-rw-r--r--src/client/views/collections/collectionGrid/Grid.tsx2
6 files changed, 207 insertions, 363 deletions
diff --git a/package-lock.json b/package-lock.json
index e692b266d..457104c8e 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -2841,8 +2841,7 @@
},
"ansi-regex": {
"version": "2.1.1",
- "bundled": true,
- "optional": true
+ "bundled": true
},
"aproba": {
"version": "1.2.0",
@@ -2860,13 +2859,11 @@
},
"balanced-match": {
"version": "1.0.0",
- "bundled": true,
- "optional": true
+ "bundled": true
},
"brace-expansion": {
"version": "1.1.11",
"bundled": true,
- "optional": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@@ -2879,18 +2876,15 @@
},
"code-point-at": {
"version": "1.1.0",
- "bundled": true,
- "optional": true
+ "bundled": true
},
"concat-map": {
"version": "0.0.1",
- "bundled": true,
- "optional": true
+ "bundled": true
},
"console-control-strings": {
"version": "1.1.0",
- "bundled": true,
- "optional": true
+ "bundled": true
},
"core-util-is": {
"version": "1.0.2",
@@ -2993,8 +2987,7 @@
},
"inherits": {
"version": "2.0.4",
- "bundled": true,
- "optional": true
+ "bundled": true
},
"ini": {
"version": "1.3.5",
@@ -3004,7 +2997,6 @@
"is-fullwidth-code-point": {
"version": "1.0.0",
"bundled": true,
- "optional": true,
"requires": {
"number-is-nan": "^1.0.0"
}
@@ -3017,20 +3009,17 @@
"minimatch": {
"version": "3.0.4",
"bundled": true,
- "optional": true,
"requires": {
"brace-expansion": "^1.1.7"
}
},
"minimist": {
"version": "1.2.5",
- "bundled": true,
- "optional": true
+ "bundled": true
},
"minipass": {
"version": "2.9.0",
"bundled": true,
- "optional": true,
"requires": {
"safe-buffer": "^5.1.2",
"yallist": "^3.0.0"
@@ -3047,7 +3036,6 @@
"mkdirp": {
"version": "0.5.3",
"bundled": true,
- "optional": true,
"requires": {
"minimist": "^1.2.5"
}
@@ -3103,8 +3091,7 @@
},
"npm-normalize-package-bin": {
"version": "1.0.1",
- "bundled": true,
- "optional": true
+ "bundled": true
},
"npm-packlist": {
"version": "1.4.8",
@@ -3129,8 +3116,7 @@
},
"number-is-nan": {
"version": "1.0.1",
- "bundled": true,
- "optional": true
+ "bundled": true
},
"object-assign": {
"version": "4.1.1",
@@ -3140,7 +3126,6 @@
"once": {
"version": "1.4.0",
"bundled": true,
- "optional": true,
"requires": {
"wrappy": "1"
}
@@ -3209,8 +3194,7 @@
},
"safe-buffer": {
"version": "5.1.2",
- "bundled": true,
- "optional": true
+ "bundled": true
},
"safer-buffer": {
"version": "2.1.2",
@@ -3240,7 +3224,6 @@
"string-width": {
"version": "1.0.2",
"bundled": true,
- "optional": true,
"requires": {
"code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0",
@@ -3258,7 +3241,6 @@
"strip-ansi": {
"version": "3.0.1",
"bundled": true,
- "optional": true,
"requires": {
"ansi-regex": "^2.0.0"
}
@@ -3297,13 +3279,11 @@
},
"wrappy": {
"version": "1.0.2",
- "bundled": true,
- "optional": true
+ "bundled": true
},
"yallist": {
"version": "3.1.1",
- "bundled": true,
- "optional": true
+ "bundled": true
}
}
}
@@ -9535,7 +9515,7 @@
},
"chownr": {
"version": "1.1.4",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
"integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg=="
},
"ci-info": {
@@ -9841,7 +9821,7 @@
},
"deep-extend": {
"version": "0.6.0",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
"integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA=="
},
"defaults": {
@@ -10340,7 +10320,7 @@
},
"glob": {
"version": "7.1.6",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
"integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
"requires": {
"fs.realpath": "^1.0.0",
@@ -10428,7 +10408,7 @@
},
"hosted-git-info": {
"version": "2.8.8",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz",
"integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg=="
},
"http-cache-semantics": {
@@ -10564,7 +10544,7 @@
},
"is-ci": {
"version": "1.2.1",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.2.1.tgz",
"integrity": "sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==",
"requires": {
"ci-info": "^1.5.0"
@@ -10640,7 +10620,7 @@
},
"is-retry-allowed": {
"version": "1.2.0",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz",
"integrity": "sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg=="
},
"is-stream": {
@@ -11149,7 +11129,7 @@
},
"mkdirp": {
"version": "0.5.4",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.4.tgz",
"integrity": "sha512-iG9AK/dJLtJ0XNgTuDbSyNS3zECqDlAhnQW4CsNxBG3LQJBbHmRX1egw39DmtOdCAqY+dKXV+sgPgilNWUKMVw==",
"requires": {
"minimist": "^1.2.5"
@@ -11157,7 +11137,7 @@
"dependencies": {
"minimist": {
"version": "1.2.5",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
}
}
@@ -11209,7 +11189,7 @@
},
"node-gyp": {
"version": "5.1.0",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-5.1.0.tgz",
"integrity": "sha512-OUTryc5bt/P8zVgNUmC6xdXiDJxLMAW8cF5tLQOT9E5sOQj+UeQxnnPy74K3CLCa/SOjjBlbuzDLR8ANwA+wmw==",
"requires": {
"env-paths": "^2.2.0",
@@ -11323,7 +11303,7 @@
},
"npm-packlist": {
"version": "1.4.8",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.8.tgz",
"integrity": "sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==",
"requires": {
"ignore-walk": "^3.0.1",
@@ -11343,7 +11323,7 @@
},
"npm-profile": {
"version": "4.0.4",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/npm-profile/-/npm-profile-4.0.4.tgz",
"integrity": "sha512-Ta8xq8TLMpqssF0H60BXS1A90iMoM6GeKwsmravJ6wYjWwSzcYBTdyWa3DZCYqPutacBMEm7cxiOkiIeCUAHDQ==",
"requires": {
"aproba": "^1.1.2 || 2",
@@ -11353,7 +11333,7 @@
},
"npm-registry-fetch": {
"version": "4.0.3",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-4.0.3.tgz",
"integrity": "sha512-WGvUx0lkKFhu9MbiGFuT9nG2NpfQ+4dCJwRwwtK2HK5izJEvwDxMeUyqbuMS7N/OkpVCqDorV6rO5E4V9F8lJw==",
"requires": {
"JSONStream": "^1.3.4",
@@ -11788,7 +11768,7 @@
},
"rc": {
"version": "1.2.8",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
"integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
"requires": {
"deep-extend": "^0.6.0",
@@ -11799,7 +11779,7 @@
"dependencies": {
"minimist": {
"version": "1.2.5",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
}
}
@@ -11858,7 +11838,7 @@
},
"readable-stream": {
"version": "3.6.0",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
"integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
"requires": {
"inherits": "^2.0.3",
@@ -11879,7 +11859,7 @@
},
"registry-auth-token": {
"version": "3.4.0",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.4.0.tgz",
"integrity": "sha512-4LM6Fw8eBQdwMYcES4yTnn2TqIasbXuwDx3um+QRs7S55aMKCBKBxvPXl2RiUjHwuJLTyYfxSpmfSAjQpcuP+A==",
"requires": {
"rc": "^1.1.6",
@@ -11943,7 +11923,7 @@
},
"rimraf": {
"version": "2.7.1",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
"integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
"requires": {
"glob": "^7.1.3"
@@ -12242,7 +12222,7 @@
},
"string_decoder": {
"version": "1.3.0",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
"integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
"requires": {
"safe-buffer": "~5.2.0"
@@ -12250,7 +12230,7 @@
"dependencies": {
"safe-buffer": {
"version": "5.2.0",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz",
"integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg=="
}
}
@@ -12562,7 +12542,7 @@
},
"widest-line": {
"version": "2.0.1",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.1.tgz",
"integrity": "sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA==",
"requires": {
"string-width": "^2.1.1"
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index 524997d20..215b5bce8 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -244,38 +244,6 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus
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
- const existingVm = ContextMenu.Instance.findByDescription("View Modes...");
- const subItems = existingVm && "subitems" in existingVm ? existingVm.subitems : [];
- subItems.push({ description: "Freeform", event: () => { this.props.Document._viewType = CollectionViewType.Freeform; }, icon: "signature" });
- if (CollectionView._safeMode) {
- ContextMenu.Instance.addItem({ description: "Test Freeform", event: () => this.props.Document._viewType = CollectionViewType.Invalid, icon: "project-diagram" });
- }
- subItems.push({ description: "Schema", event: () => this.props.Document._viewType = CollectionViewType.Schema, icon: "th-list" });
- subItems.push({ description: "Treeview", event: () => this.props.Document._viewType = CollectionViewType.Tree, icon: "tree" });
- subItems.push({ description: "Stacking", event: () => this.props.Document._viewType = CollectionViewType.Stacking, icon: "ellipsis-v" });
- subItems.push({
- description: "Stacking (AutoHeight)", event: () => {
- this.props.Document._viewType = CollectionViewType.Stacking;
- this.props.Document._autoHeight = true;
- }, icon: "ellipsis-v"
- });
- subItems.push({ description: "Staff", event: () => this.props.Document._viewType = CollectionViewType.Staff, icon: "music" });
- subItems.push({ description: "Multicolumn", event: () => this.props.Document._viewType = CollectionViewType.Multicolumn, icon: "columns" });
- subItems.push({ description: "Multirow", event: () => this.props.Document._viewType = CollectionViewType.Multirow, icon: "columns" });
- subItems.push({ description: "Masonry", event: () => this.props.Document._viewType = CollectionViewType.Masonry, icon: "columns" });
- subItems.push({ description: "Carousel", event: () => this.props.Document._viewType = CollectionViewType.Carousel, icon: "columns" });
- subItems.push({ description: "Pivot/Time", event: () => this.props.Document._viewType = CollectionViewType.Time, icon: "columns" });
- subItems.push({ description: "Map", event: () => this.props.Document._viewType = CollectionViewType.Map, icon: "globe-americas" });
- subItems.push({ description: "Grid", event: () => this.props.Document._viewType = CollectionViewType.Grid, icon: "th-list" });
- switch (this.props.Document._viewType) {
- case CollectionViewType.Freeform: {
- subItems.push({ description: "Custom", icon: "fingerprint", event: AddCustomFreeFormLayout(this.props.Document, this.props.fieldKey) });
- break;
- }
- }
- subItems.push({ description: "lightbox", event: action(() => this._isLightboxOpen = true), icon: "eye" });
- !existingVm && ContextMenu.Instance.addItem({ description: "View Modes...", subitems: subItems, icon: "eye" });
-
this.setupViewTypes("Add a Perspective...", vtype => {
const newRendition = Doc.MakeAlias(this.props.Document);
newRendition._viewType = vtype;
diff --git a/src/client/views/collections/CollectionViewChromes.tsx b/src/client/views/collections/CollectionViewChromes.tsx
index 63080d2e6..53bff0fe5 100644
--- a/src/client/views/collections/CollectionViewChromes.tsx
+++ b/src/client/views/collections/CollectionViewChromes.tsx
@@ -16,6 +16,7 @@ import { CollectionViewType } from "./CollectionView";
import { CollectionView } from "./CollectionView";
import "./CollectionViewChromes.scss";
import { CollectionFreeFormDocumentView } from "../nodes/CollectionFreeFormDocumentView";
+import { undo } from "prosemirror-history";
const datepicker = require('js-datepicker');
interface CollectionViewChromeProps {
@@ -589,14 +590,16 @@ export class CollectionGridViewChrome extends React.Component<CollectionViewChro
this.resizeListenerDisposer?.();
}
+ get numCols() { return NumCast(this.props.CollectionView.props.Document.gridNumCols, 10); }
+
/**
* Sets the value of `numCols` on the grid's Document to the value entered.
*/
@undoBatch
onNumColsEnter = (e: React.KeyboardEvent<HTMLInputElement>) => {
if (e.key === "Enter" || e.key === "Tab") {
- if (e.currentTarget.valueAsNumber > 0 && this.props.CollectionView.props.Document.numCols as number !== e.currentTarget.valueAsNumber) {
- this.props.CollectionView.props.Document.numCols = e.currentTarget.valueAsNumber;
+ if (e.currentTarget.valueAsNumber > 0) {
+ this.props.CollectionView.props.Document.gridNumCols = e.currentTarget.valueAsNumber;
}
}
@@ -617,8 +620,9 @@ export class CollectionGridViewChrome extends React.Component<CollectionViewChro
/**
* Sets whether the grid is flexible or not on the grid's Document.
*/
+ @undoBatch
toggleFlex = () => {
- this.props.CollectionView.props.Document.flexGrid = !this.props.CollectionView.props.Document.flexGrid;
+ this.props.CollectionView.props.Document.gridFlex = !this.props.CollectionView.props.Document.gridFlex;
}
/**
@@ -626,8 +630,8 @@ export class CollectionGridViewChrome extends React.Component<CollectionViewChro
*/
onIncrementButtonClick = () => {
this.clicked = true;
- this.entered && (this.props.CollectionView.props.Document.numCols as number)--;
- undoBatch(() => (this.props.CollectionView.props.Document.numCols as number)++)();
+ this.entered && (this.props.CollectionView.props.Document.gridNumCols as number)--;
+ undoBatch(() => this.props.CollectionView.props.Document.gridNumCols = this.numCols + 1)();
this.entered = false;
}
@@ -637,8 +641,8 @@ export class CollectionGridViewChrome extends React.Component<CollectionViewChro
onDecrementButtonClick = () => {
this.clicked = true;
if (!this.decrementLimitReached) {
- this.entered && (this.props.CollectionView.props.Document.numCols as number)++;
- undoBatch(() => (this.props.CollectionView.props.Document.numCols as number)--)();
+ this.entered && (this.props.CollectionView.props.Document.gridNumCols as number)++;
+ undoBatch(() => this.props.CollectionView.props.Document.gridNumCols = this.numCols - 1)();
}
this.entered = false;
}
@@ -649,7 +653,7 @@ export class CollectionGridViewChrome extends React.Component<CollectionViewChro
incrementValue = () => {
this.entered = true;
if (!this.clicked && !this.decrementLimitReached) {
- (this.props.CollectionView.props.Document.numCols as number)++;
+ this.props.CollectionView.props.Document.gridNumCols = this.numCols + 1;
}
this.decrementLimitReached = false;
this.clicked = false;
@@ -661,8 +665,8 @@ export class CollectionGridViewChrome extends React.Component<CollectionViewChro
decrementValue = () => {
this.entered = true;
if (!this.clicked) {
- if (this.props.CollectionView.props.Document.numCols as number !== 1) {
- (this.props.CollectionView.props.Document.numCols as number)--;
+ if (this.numCols !== 1) {
+ this.props.CollectionView.props.Document.gridNumCols = this.numCols - 1;
}
else {
this.decrementLimitReached = true;
@@ -676,14 +680,15 @@ export class CollectionGridViewChrome extends React.Component<CollectionViewChro
* Toggles the value of preventCollision
*/
toggleCollisions = () => {
- this.props.CollectionView.props.Document.preventCollision = !this.props.CollectionView.props.Document.preventCollision;
+ this.props.CollectionView.props.Document.gridPreventCollision = !this.props.CollectionView.props.Document.gridPreventCollision;
}
/**
* Changes the value of the compactType
*/
+ @undoBatch
changeCompactType = (e: React.ChangeEvent<HTMLSelectElement>) => {
- this.props.CollectionView.props.Document.compactType = e.target.selectedOptions[0].value;
+ this.props.CollectionView.props.Document.gridCompaction = e.target.selectedOptions[0].value;
}
render() {
@@ -693,7 +698,7 @@ export class CollectionGridViewChrome extends React.Component<CollectionViewChro
<span className="grid-icon">
<FontAwesomeIcon icon="columns" size="1x" />
</span>
- <input className="collectionGridViewChrome-entryBox" type="number" placeholder={this.props.CollectionView.props.Document.numCols as string} onKeyDown={this.onNumColsEnter} onClick={(e: React.MouseEvent<HTMLInputElement, MouseEvent>) => { e.stopPropagation(); e.preventDefault(); e.currentTarget.focus(); }} />
+ <input className="collectionGridViewChrome-entryBox" type="number" placeholder={this.numCols.toString()} onKeyDown={this.onNumColsEnter} onClick={(e: React.MouseEvent<HTMLInputElement, MouseEvent>) => { e.stopPropagation(); e.preventDefault(); e.currentTarget.focus(); }} />
<input className="columnButton" onClick={this.onIncrementButtonClick} onMouseEnter={this.incrementValue} onMouseLeave={this.decrementValue} type="button" value="↑" />
<input className="columnButton" style={{ marginRight: 5 }} onClick={this.onDecrementButtonClick} onMouseEnter={this.decrementValue} onMouseLeave={this.incrementValue} type="button" value="↓" />
</span>
@@ -704,7 +709,7 @@ export class CollectionGridViewChrome extends React.Component<CollectionViewChro
<input className="collectionGridViewChrome-entryBox" type="number" placeholder={this.props.CollectionView.props.Document.rowHeight as string} onKeyDown={this.onRowHeightEnter} onClick={(e: React.MouseEvent<HTMLInputElement, MouseEvent>) => { e.stopPropagation(); e.preventDefault(); e.currentTarget.focus(); }} />
</span> */}
<span className="grid-control" style={{ width: this.resize ? "12%" : "20%" }}>
- <input type="checkbox" style={{ marginRight: 5 }} onClick={this.toggleCollisions} defaultChecked={!this.props.CollectionView.props.Document.preventCollision} />
+ <input type="checkbox" style={{ marginRight: 5 }} onClick={this.toggleCollisions} defaultChecked={!this.props.CollectionView.props.Document.gridPreventCollision} />
<label className="flexLabel">{this.resize ? "Coll" : "Collisions"}</label>
</span>
@@ -712,7 +717,7 @@ export class CollectionGridViewChrome extends React.Component<CollectionViewChro
style={{ marginRight: 5 }}
onPointerDown={stopPropagation}
onChange={this.changeCompactType}
- value={StrCast(this.props.CollectionView.props.Document.compactType)}>
+ value={StrCast(this.props.CollectionView.props.Document.gridCompaction)}>
>
{["vertical", "horizontal", "null"].map(type =>
<option className="collectionGridViewChrome-viewOption"
@@ -724,11 +729,11 @@ export class CollectionGridViewChrome extends React.Component<CollectionViewChro
</select>
<span className="grid-control" style={{ width: this.resize ? "12%" : "20%" }}>
- <input style={{ marginRight: 5 }} type="checkbox" onClick={this.toggleFlex} defaultChecked={this.props.CollectionView.props.Document.flexGrid as boolean} />
+ <input style={{ marginRight: 5 }} type="checkbox" onClick={this.toggleFlex} defaultChecked={BoolCast(this.props.CollectionView.props.Document.gridFlex)} />
<label className="flexLabel">{this.resize ? "Flex" : "Flexible"}</label>
</span>
- <button onClick={() => this.props.CollectionView.props.Document.resetLayout = true}>
+ <button onClick={() => this.props.CollectionView.props.Document.gridResetLayout = true}>
{!this.resize ? "Reset" :
<FontAwesomeIcon icon="redo-alt" size="1x" />}
</button>
diff --git a/src/client/views/collections/collectionGrid/CollectionGridView.scss b/src/client/views/collections/collectionGrid/CollectionGridView.scss
index de7d62475..9c2d5cbff 100644
--- a/src/client/views/collections/collectionGrid/CollectionGridView.scss
+++ b/src/client/views/collections/collectionGrid/CollectionGridView.scss
@@ -21,6 +21,10 @@
max-width: 100%;
}
+ .react-grid-layout {
+ width : 100%;
+ }
+
.react-grid-item>.react-resizable-handle {
z-index: 4; // doesn't work on prezi otherwise
}
@@ -41,7 +45,7 @@
position: absolute;
height: 3;
left: 5;
- top: 40;
+ top: 30;
transform-origin: left;
transform: rotate(90deg);
outline: none;
diff --git a/src/client/views/collections/collectionGrid/CollectionGridView.tsx b/src/client/views/collections/collectionGrid/CollectionGridView.tsx
index a820b7e0e..2e1f7a0db 100644
--- a/src/client/views/collections/collectionGrid/CollectionGridView.tsx
+++ b/src/client/views/collections/collectionGrid/CollectionGridView.tsx
@@ -1,85 +1,61 @@
-import { computed, observable, Lambda, action, reaction } from 'mobx';
+import { action, computed, Lambda, observable, reaction } from 'mobx';
+import { observer } from 'mobx-react';
import * as React from "react";
import { Doc, Opt } from '../../../../fields/Doc';
import { documentSchema } from '../../../../fields/documentSchemas';
+import { Id } from '../../../../fields/FieldSymbols';
import { makeInterface } from '../../../../fields/Schema';
-import { BoolCast, NumCast, StrCast, ScriptCast } from '../../../../fields/Types';
+import { BoolCast, NumCast, ScriptCast, StrCast } from '../../../../fields/Types';
+import { emptyFunction, returnFalse, returnZero, setupMoveUpEvents } from '../../../../Utils';
+import { Docs } from '../../../documents/Documents';
+import { DragManager } from '../../../util/DragManager';
+import { SnappingManager } from '../../../util/SnappingManager';
import { Transform } from '../../../util/Transform';
import { undoBatch } from '../../../util/UndoManager';
+import { ContextMenu } from '../../ContextMenu';
+import { ContextMenuProps } from '../../ContextMenuItem';
import { ContentFittingDocumentView } from '../../nodes/ContentFittingDocumentView';
+import { FormattedTextBox } from '../../nodes/formattedText/FormattedTextBox';
import { CollectionSubView } from '../CollectionSubView';
-import { SubCollectionViewProps } from '../CollectionSubView';
-import { returnZero } from '../../../../Utils';
-import Grid, { Layout } from "./Grid";
-import { Id } from '../../../../fields/FieldSymbols';
-import { observer } from 'mobx-react';
-import { SnappingManager } from '../../../util/SnappingManager';
-import { Docs } from '../../../documents/Documents';
-import { EditableView, EditableProps } from '../../EditableView';
import "./CollectionGridView.scss";
-import { ContextMenu } from '../../ContextMenu';
-import { List } from '../../../../fields/List';
-import { ContextMenuProps } from '../../ContextMenuItem';
-
+import Grid, { Layout } from "./Grid";
type GridSchema = makeInterface<[typeof documentSchema]>;
const GridSchema = makeInterface(documentSchema);
@observer
export class CollectionGridView extends CollectionSubView(GridSchema) {
- private containerRef: React.RefObject<HTMLDivElement>;
+ private _containerRef: React.RefObject<HTMLDivElement> = React.createRef();
+ private _changeListenerDisposer: Opt<Lambda>; // listens for changes in this.childLayoutPairs
+ private _resetListenerDisposer: Opt<Lambda>; // listens for when the reset button is clicked
+ @observable private _rowHeight: Opt<number>; // temporary store of row height to make change undoable
@observable private _scroll: number = 0; // required to make sure the decorations box container updates on scroll
- private changeListenerDisposer: Opt<Lambda>; // listens for changes in this.childLayoutPairs
- private rowHeight: number = 0; // temporary store of row height to make change undoable
- private mounted: boolean = false; // hack to fix the issue of not rerendering when mounting
- private resetListenerDisposer: Opt<Lambda>; // listens for when the reset button is clicked
-
- constructor(props: Readonly<SubCollectionViewProps>) {
- super(props);
-
- this.props.Document.numCols = NumCast(this.props.Document.numCols, 10);
- this.props.Document.rowHeight = NumCast(this.props.Document.rowHeight, 100);
-
- // determines whether the grid is static/flexible i.e. whether can nodes be moved around and resized or not
- this.props.Document.flexGrid = BoolCast(this.props.Document.flexGrid, true);
- // determines whether nodes should remain in position, be bound to the top, or to the left
- this.props.Document.compactType = StrCast(this.props.Document.compactType, "vertical");
-
- // determines whether nodes should move out of the way (i.e. collide) when other nodes are dragged over them
- this.props.Document.preventCollision = BoolCast(this.props.Document.preventCollision, false);
+ @computed get onChildClickHandler() { return ScriptCast(this.Document.onChildClick); }
- // sets the default width and height of the grid nodes
- this.props.Document.defaultW = NumCast(this.props.Document.defaultW, 2);
- this.props.Document.defaultH = NumCast(this.props.Document.defaultH, 2);
+ @computed get numCols() { return NumCast(this.props.Document.gridNumCols, 10); }
+ @computed get rowHeight() { return this._rowHeight === undefined ? NumCast(this.props.Document.gridRowHeight, 100) : this._rowHeight; }
+ // sets the default width and height of the grid nodes
+ @computed get defaultW() { return NumCast(this.props.Document.gridDefaultW, 2); }
+ @computed get defaultH() { return NumCast(this.props.Document.gridDefaultH, 2); }
- // sets the margin between grid nodes
- this.props.Document.margin = NumCast(this.props.Document.margin, 10);
+ @computed get colWidthPlusGap() { return (this.props.PanelWidth() - this.margin) / this.numCols; }
+ @computed get rowHeightPlusGap() { return this.rowHeight + this.margin; }
- // sets the css display type of the ContentFittingDocumentView component
- this.props.Document.display = StrCast(this.props.Document.display, "contents");
+ @computed get margin() { return NumCast(this.props.Document.margin, 10); } // sets the margin between grid nodes
- this.setLayout = this.setLayout.bind(this);
- this.onSliderChange = this.onSliderChange.bind(this);
- this.onContextMenu = this.onContextMenu.bind(this);
-
- this.containerRef = React.createRef();
- }
+ @computed get flexGrid() { return BoolCast(this.props.Document.gridFlex, true); } // is grid static/flexible i.e. whether nodes be moved around and resized
componentDidMount() {
- this.mounted = true;
-
- this.changeListenerDisposer = computed(() => this.childLayoutPairs).observe(({ oldValue, newValue }) => {
-
- const layouts: Layout[] = this.parsedLayoutList;
+ this._changeListenerDisposer = computed(() => this.childLayoutPairs).observe(({ oldValue, newValue }) => {
+ const layouts = this.parsedLayoutList;
// if grid view has been opened and then exited and a document has been deleted
// this deletes the layout of that document from the layouts list
if (!oldValue && newValue.length) {
layouts.forEach(({ i }, index) => {
- const targetId = i;
- if (!newValue.find(({ layout: preserved }) => preserved[Id] === targetId)) {
+ if (!newValue.find(({ layout: preserved }) => preserved[Id] === i)) {
layouts.splice(index, 1);
}
});
@@ -88,120 +64,84 @@ export class CollectionGridView extends CollectionSubView(GridSchema) {
if (!oldValue || newValue.length > oldValue.length) {
// for each document that was added, add a corresponding grid layout object
newValue.forEach(({ layout }, i) => {
- const targetId = layout[Id];
- if (!layouts.find((gridLayout: Layout) => gridLayout.i === targetId)) {
- layouts.push({
- i: targetId,
- w: this.defaultW,
- h: this.defaultH,
- x: this.defaultW * (i % Math.floor(NumCast(this.props.Document.numCols) / this.defaultW)),
- y: this.defaultH * Math.floor(i / Math.floor(NumCast(this.props.Document.numCols) / this.defaultH)),
- static: !this.props.Document.flexGrid
- });
+ if (!layouts.find(gridLayout => gridLayout.i === layout[Id])) {
+ this.addLayoutItem(layouts, this.makeLayoutItem(layout, this.unflexedPosition(i), !this.flexGrid))
}
- });
+ })
} else {
// for each document that was removed, remove its corresponding grid layout object
oldValue.forEach(({ layout }) => {
- const targetId = layout[Id];
- if (!newValue.find(({ layout: preserved }) => preserved[Id] === targetId)) {
- const index = layouts.findIndex((gridLayout: Layout) => gridLayout.i === targetId);
+ if (!newValue.find(({ layout: preserved }) => preserved[Id] === layout[Id])) {
+ const index = layouts.findIndex((gridLayout: Layout) => gridLayout.i === layout[Id]);
index !== -1 && layouts.splice(index, 1);
}
});
}
- this.unStringifiedLayoutList = layouts;
+ this.setLayoutList(layouts);
}, true);
// updates the layouts if the reset button has been clicked
- this.resetListenerDisposer = reaction(() => this.props.Document.resetLayout, () => {
- if (this.props.Document.flexGrid) {
- const layouts: Layout[] = this.parsedLayoutList;
- this.setLayout(
- layouts.map(({ i }, index) => ({
- i: i,
- x: this.defaultW * (index % Math.floor(NumCast(this.props.Document.numCols) / this.defaultW)),
- y: this.defaultH * Math.floor(index / Math.floor(NumCast(this.props.Document.numCols) / this.defaultH)),
- w: this.defaultW,
- h: this.defaultH,
- })));
+ this._resetListenerDisposer = reaction(() => this.props.Document.gridResetLayout, (reset) => {
+ if (reset && this.flexGrid) {
+ this.setLayout(this.childLayoutPairs.map((pair, index) => this.makeLayoutItem(pair.layout, this.unflexedPosition(index))));
}
- this.props.Document.resetLayout = false;
+ this.props.Document.gridResetLayout = false;
});
}
componentWillUnmount() {
- this.mounted = false;
- this.changeListenerDisposer && this.changeListenerDisposer();
- this.resetListenerDisposer?.();
+ this._changeListenerDisposer?.();
+ this._resetListenerDisposer?.();
}
- /**
- * @returns the transform that will correctly place the document decorations box.
- */
- private lookupIndividualTransform = (layout: Layout) => {
- const index = this.childLayoutPairs.findIndex(({ layout: layoutDoc }) => layoutDoc[Id] === layout.i);
-
- // translations depend on whether the grid is flexible or static
- const xTranslation = (this.props.Document.flexGrid ? NumCast(layout.x) : this.defaultW * (index % Math.floor(NumCast(this.props.Document.numCols) / this.defaultW))) * this.colWidthPlusGap + this.margin;
- const yTranslation = (this.props.Document.flexGrid ? NumCast(layout.y) : this.defaultH * Math.floor(index / Math.floor(NumCast(this.props.Document.numCols) / this.defaultH))) * this.rowHeightPlusGap + this.margin - this._scroll + 30; // 30 is the height of the add text doc bar
-
- return this.props.ScreenToLocalTransform().translate(-xTranslation, -yTranslation);
+ unflexedPosition(index: number) {
+ return {
+ x: (index % Math.floor(this.numCols / this.defaultW)) * this.defaultW,
+ y: Math.floor(index / Math.floor(this.numCols / this.defaultH)) * this.defaultH
+ };
}
- @computed get onChildClickHandler() { return ScriptCast(this.Document.onChildClick); }
+ screenToCell(sx: number, sy: number) {
+ const pt = this.props.ScreenToLocalTransform().transformPoint(sx, sy);
+ const x = Math.floor(pt[0] / this.colWidthPlusGap);
+ const y = Math.floor((pt[1] + this._scroll) / this.rowHeight);
+ return { x, y };
+ }
- addDocTab = (doc: Doc, where: string) => {
- if (where === "inPlace" && this.layoutDoc.isInPlaceContainer) {
- this.dataDoc[this.props.fieldKey] = new List<Doc>([doc]);
- return true;
- }
- return this.props.addDocTab(doc, where);
+ makeLayoutItem = (doc: Doc, pos: { x: number, y: number }, Static: boolean = false, w: number = this.defaultW, h: number = this.defaultH) => {
+ return ({ i: doc[Id], w, h, x: pos.x, y: pos.y, static: Static });
}
- @computed get colWidthPlusGap() { return (this.props.PanelWidth() - this.margin) / NumCast(this.props.Document.numCols); }
- @computed get rowHeightPlusGap() { return NumCast(this.props.Document.rowHeight) + this.margin; }
+ addLayoutItem = (layouts: Layout[], layout: Layout) => {
+ const f = layouts.findIndex(l => l.i === layout.i);
+ f !== -1 && layouts.splice(f, 1);
+ layouts.push(layout);
+ return layouts;
+ }
+ /**
+ * @returns the transform that will correctly place the document decorations box.
+ */
+ private lookupIndividualTransform = (layout: Layout) => {
+ const xypos = this.flexGrid ? layout : this.unflexedPosition(this.layoutList.findIndex(l => l.i === layout.i));
+ const pos = { x: xypos.x * this.colWidthPlusGap + this.margin, y: xypos.y * this.rowHeightPlusGap + this.margin - this._scroll };
- @computed get margin() { return NumCast(this.props.Document.margin); }
- @computed get defaultW() { return NumCast(this.props.Document.defaultW); }
- @computed get defaultH() { return NumCast(this.props.Document.defaultH); }
+ return this.props.ScreenToLocalTransform().translate(-pos.x, -pos.y);
+ }
/**
* @returns the layout list converted from JSON
*/
get parsedLayoutList() {
- return this.props.Document.gridLayoutString ? JSON.parse(StrCast(this.props.Document.gridLayoutString)) : [];
+ return (this.props.Document.gridLayoutString ? JSON.parse(StrCast(this.props.Document.gridLayoutString)) : []) as Layout[];
}
/**
* Stores the layout list on the Document as JSON
*/
- set unStringifiedLayoutList(layouts: Layout[]) {
-
- // sometimes there are issues with rendering when you switch from a different view
- // where the nodes are all squeezed together on the left hand side of the screen
- // until you click on the screen or close the chrome or interact with it in some way
- // the component doesn't rerender when the component mounts
- // this seems to fix that though it isn't very elegant
-
- this.mounted && (this.props.Document.gridLayoutString = "");
+ setLayoutList(layouts: Layout[]) {
this.props.Document.gridLayoutString = JSON.stringify(layouts);
- this.mounted = false;
}
-
- /**
- * Sets the width of the decorating box.
- * @param layout
- */
- @observable private width = (layout: Layout) => (this.props.Document.flexGrid ? layout.w : this.defaultW) * this.colWidthPlusGap - this.margin;
-
- /**
- * Sets the height of the decorating box.
- * @param layout
- */
- @observable private height = (layout: Layout) => (this.props.Document.flexGrid ? layout.h : this.defaultH) * this.rowHeightPlusGap - this.margin;
-
/**
*
* @param layout
@@ -217,7 +157,6 @@ export class CollectionGridView extends CollectionSubView(GridSchema) {
DataDoc={layout.resolvedDataDoc as Doc}
NativeHeight={returnZero}
NativeWidth={returnZero}
- addDocTab={this.addDocTab}
backgroundColor={this.props.backgroundColor}
ContainingCollectionDoc={this.props.Document}
PanelWidth={width}
@@ -226,7 +165,7 @@ export class CollectionGridView extends CollectionSubView(GridSchema) {
onClick={this.onChildClickHandler}
renderDepth={this.props.renderDepth + 1}
parentActive={this.props.active}
- display={StrCast(this.props.Document.display)}
+ display={StrCast(this.props.Document.display, "contents")} // sets the css display type of the ContentFittingDocumentView component
/>;
}
@@ -234,27 +173,18 @@ export class CollectionGridView extends CollectionSubView(GridSchema) {
* Saves the layouts received from the Grid to the Document.
* @param layouts `Layout[]`
*/
- @undoBatch
@action
- setLayout(layoutArray: Layout[]) {
+ setLayout = (layoutArray: Layout[]) => {
// for every child in the collection, check to see if there's a corresponding grid layout object and
// updated layout object. If both exist, which they should, update the grid layout object from the updated object
-
- if (this.props.Document.flexGrid) {
- const layouts: Layout[] = this.parsedLayoutList;
+ if (this.flexGrid) {
+ const layouts = this.parsedLayoutList;
this.childLayoutPairs.forEach(({ layout: doc }) => {
- let update: Opt<Layout>;
- const targetId = doc[Id];
- const gridLayout = layouts.find(gridLayout => gridLayout.i === targetId);
- if (gridLayout && (update = layoutArray.find(layout => layout.i === targetId))) {
- gridLayout.x = update.x;
- gridLayout.y = update.y;
- gridLayout.w = update.w;
- gridLayout.h = update.h;
- }
+ let gridLayout = layouts.find(gridLayout => gridLayout.i === doc[Id]);
+ gridLayout && Object.assign(gridLayout, layoutArray.find(layout => layout.i === doc[Id]) || gridLayout);
});
- this.unStringifiedLayoutList = layouts;
+ this.setLayoutList(layouts);
}
}
@@ -264,27 +194,22 @@ export class CollectionGridView extends CollectionSubView(GridSchema) {
*/
@computed
private get contents(): JSX.Element[] {
-
- const { childLayoutPairs } = this;
const collector: JSX.Element[] = [];
- const layouts: Layout[] = this.parsedLayoutList;
- if (!layouts.length || layouts.length !== childLayoutPairs.length) {
- return [];
- }
-
- for (let i = 0; i < childLayoutPairs.length; i++) {
- const { layout } = childLayoutPairs[i];
- const gridLayout = layouts[i];
- const dxf = () => this.lookupIndividualTransform(gridLayout);
- const width = () => this.width(gridLayout);
- const height = () => this.height(gridLayout);
- collector.push(
- <div className={this.props.Document.flexGrid && (this.props.isSelected() ? true : false) ? "document-wrapper" : "document-wrapper static"}
- key={gridLayout.i}
- >
- {this.getDisplayDoc(layout, dxf, width, height)}
- </div >
- );
+ const layouts = this.parsedLayoutList;
+ if (layouts.length !== this.childLayoutPairs.length) {
+ setTimeout(action(() => this.props.Document.gridResetLayout = true), 0);
+ } else {
+ this.layoutList.forEach((l, i) => {
+ const child = this.childLayoutPairs.find(c => c.layout[Id] === l.i);
+ const dxf = () => this.lookupIndividualTransform(layouts[i]);
+ const width = () => (this.flexGrid ? layouts[i].w : this.defaultW) * this.colWidthPlusGap - this.margin;
+ const height = () => (this.flexGrid ? layouts[i].h : this.defaultH) * this.rowHeightPlusGap - this.margin;
+ child && collector.push(
+ <div key={child.layout[Id]} className={"document-wrapper" + (this.flexGrid && this.props.isSelected() ? "" : " static")} >
+ {this.getDisplayDoc(child.layout, dxf, width, height)}
+ </div >
+ );
+ });
}
return collector;
}
@@ -293,56 +218,42 @@ export class CollectionGridView extends CollectionSubView(GridSchema) {
* @returns a list of `Layout` objects with attributes depending on whether the grid is flexible or static
*/
get layoutList(): Layout[] {
-
- const layouts: Layout[] = this.parsedLayoutList;
-
- return this.props.Document.flexGrid ?
- layouts.map(({ i, x, y, w, h }) => ({
- i: i,
- x: x + w > NumCast(this.props.Document.numCols) ? 0 : x, // handles wrapping around of nodes when numCols decreases
- y: y,
- w: w > NumCast(this.props.Document.numCols) ? NumCast(this.props.Document.numCols) : w, // reduces width if greater than numCols
- h: h,
+ return this.flexGrid ?
+ this.parsedLayoutList.map(({ i, x, y, w, h }) => ({
+ i, y, h,
+ x: x + w > this.numCols ? 0 : x, // handles wrapping around of nodes when numCols decreases
+ w: Math.max(w, this.numCols), // reduces width if greater than numCols
static: BoolCast(this.childLayoutPairs.find(({ layout }) => layout[Id] === i)?.layout.lockedPosition, false) // checks if the lock position item has been selected in the context menu
- }))
- : layouts.map(({ i }, index) => ({
- i: i,
- x: this.defaultW * (index % Math.floor(NumCast(this.props.Document.numCols) / this.defaultW)),
- y: this.defaultH * Math.floor(index / Math.floor(NumCast(this.props.Document.numCols) / this.defaultH)),
- w: this.defaultW,
- h: this.defaultH,
- static: true
- }));
+ })) :
+ this.parsedLayoutList.map((layout, index) => Object.assign(layout, this.unflexedPosition(index)));
}
- /**
- * Handles the change in the value of the rowHeight slider.
- */
- onSliderChange = (event: React.ChangeEvent<HTMLInputElement>) => {
- this.props.Document.rowHeight = event.currentTarget.valueAsNumber;
+ onInternalDrop = (e: Event, de: DragManager.DropEvent) => {
+ const layouts = this.parsedLayoutList;
+ const dropped = de.complete.docDragData?.droppedDocuments;
+ if (dropped && super.onInternalDrop(e, de) && layouts.length !== this.childDocs.length) {
+ dropped.forEach(doc => this.addLayoutItem(layouts, this.makeLayoutItem(doc, this.screenToCell(de.x, de.y)))); // shouldn't place all docs in the same cell;
+ this.setLayoutList(layouts);
+ return true;
+ }
+ return false;
}
/**
- * Saves the rowHeight in a temporary variable to make it undoable later.
+ * Handles the change in the value of the rowHeight slider.
*/
- onSliderDown = () => {
- this.rowHeight = NumCast(this.props.Document.rowHeight);
+ @action
+ onSliderChange = (event: React.ChangeEvent<HTMLInputElement>) => {
+ this._rowHeight = event.currentTarget.valueAsNumber;
}
-
- /**
- * Uses the stored rowHeight to make the rowHeight change undoable.
- */
- onSliderUp = () => {
- const tempVal = this.props.Document.rowHeight;
- this.props.Document.rowHeight = this.rowHeight;
- undoBatch(() => this.props.Document.rowHeight = tempVal)();
+ @action
+ onSliderDown = (e: React.PointerEvent) => {
+ this._rowHeight = this.rowHeight; // uses _rowHeight during dragging and sets doc's rowHeight when finished so that operation is undoable
+ setupMoveUpEvents(this, e, returnFalse, action(() => {
+ undoBatch(() => this.props.Document.gridRowHeight = this._rowHeight)();
+ this._rowHeight = undefined;
+ }), emptyFunction, false, false);
}
-
- /**
- * Creates a text document and adds it to the grid.
- */
- @undoBatch @action addTextDocument = (value: string) => this.props.addDocument(Docs.Create.TextDocument(value, { title: value }));
-
/**
* Adds the display option to change the css display attribute of the `ContentFittingDocumentView`s
*/
@@ -350,74 +261,52 @@ export class CollectionGridView extends CollectionSubView(GridSchema) {
const displayOptionsMenu: ContextMenuProps[] = [];
displayOptionsMenu.push({ description: "Contents", event: () => this.props.Document.display = "contents", icon: "copy" });
displayOptionsMenu.push({ description: "Undefined", event: () => this.props.Document.display = undefined, icon: "exclamation" });
-
ContextMenu.Instance.addItem({ description: "Display", subitems: displayOptionsMenu, icon: "tv" });
}
- render() {
-
- // for the add text document EditableView
- const newEditableViewProps: EditableProps = {
- GetValue: () => "",
- SetValue: this.addTextDocument,
- contents: "+ ADD TEXT DOCUMENT",
- };
-
- const childDocumentViews: JSX.Element[] = this.contents;
- const chromeStatus = this.props.Document._chromeStatus;
- const showChrome = (chromeStatus !== 'view-mode' && chromeStatus !== 'disabled');
+ onPointerDown = (e: React.PointerEvent) => {
+ this.props.isSelected(true) && setupMoveUpEvents(this, e, returnFalse, returnFalse, action((e: PointerEvent, doubleTap?: boolean) => {
+ if (doubleTap) {
+ const text = Docs.Create.TextDocument("", { _width: 150, _height: 50 });
+ FormattedTextBox.SelectOnLoad = text[Id];// track the new text box so we can give it a prop that tells it to focus itself when it's displayed
+ Doc.AddDocToList(this.props.Document, this.props.fieldKey, text);
+ this.setLayoutList(this.addLayoutItem(this.parsedLayoutList, this.makeLayoutItem(text, this.screenToCell(e.clientX, e.clientY))));
+ }
+ }), false);
+ e.stopPropagation();
+ }
+ render() {
return (
- <div className="collectionGridView-contents"
- style={{
- pointerEvents: !this.props.active() && !SnappingManager.GetIsDragging() ? "none" : undefined
- }}
+ <div className="collectionGridView-contents" ref={this.createDashEventsTarget}
+ style={{ pointerEvents: !this.props.active() && !SnappingManager.GetIsDragging() ? "none" : undefined }}
onContextMenu={this.onContextMenu}
- ref={this.createDashEventsTarget}
- onPointerDown={e => {
- if (this.props.active(true)) {
- if (this.props.isSelected(true)) {
- e.stopPropagation();
- }
- }
- // is the following section needed? it prevents the slider from being easily used and I'm not sure what it's preventing
-
- // if (this.props.isSelected(true)) {
- // !((e.target as any)?.className.includes("react-resizable-handle")) && e.preventDefault();
- // }
-
- }} // the grid doesn't stopPropagation when its widgets are hit, so we need to otherwise the outer documents will respond
- >
- {showChrome ?
- <div className="collectionGridView-addDocumentButton">
- <EditableView {...newEditableViewProps} />
- </div> : null
- }
- <div className="collectionGridView-gridContainer"
- ref={this.containerRef}
+ onPointerDown={e => this.onPointerDown(e)} >
+ <div className="collectionGridView-gridContainer" ref={this._containerRef}
+ onWheel={e => e.stopPropagation()}
onScroll={action(e => {
if (!this.props.isSelected()) e.currentTarget.scrollTop = this._scroll;
else this._scroll = e.currentTarget.scrollTop;
- })}
- onWheel={e => e.stopPropagation()}
- >
- <input className="rowHeightSlider" type="range" value={NumCast(this.props.Document.rowHeight)} onPointerDown={this.onSliderDown} onPointerUp={this.onSliderUp} onChange={this.onSliderChange} style={{ width: this.props.PanelHeight() - 40 }} min={1} max={this.props.PanelHeight() - 40} />
+ })} >
+ <input className="rowHeightSlider" type="range"
+ style={{ width: this.props.PanelHeight() - 30 }}
+ min={1} value={this.rowHeight} max={this.props.PanelHeight() - 30}
+ onPointerDown={this.onSliderDown} onChange={this.onSliderChange} />
<Grid
width={this.props.PanelWidth()}
- nodeList={childDocumentViews.length ? childDocumentViews : null}
- layout={childDocumentViews.length ? this.layoutList : undefined}
+ nodeList={this.contents.length ? this.contents : null}
+ layout={this.contents.length ? this.layoutList : undefined}
childrenDraggable={this.props.isSelected() ? true : false}
- numCols={NumCast(this.props.Document.numCols)}
- rowHeight={NumCast(this.props.Document.rowHeight)}
+ numCols={this.numCols}
+ rowHeight={this.rowHeight}
setLayout={this.setLayout}
transformScale={this.props.ScreenToLocalTransform().Scale}
- compactType={StrCast(this.props.Document.compactType)}
- preventCollision={BoolCast(this.props.Document.preventCollision)}
+ compactType={StrCast(this.props.Document.gridCompaction, "vertical")} // determines whether nodes should remain in position, be bound to the top, or to the left
+ preventCollision={BoolCast(this.props.Document.gridPreventCollision)}// determines whether nodes should move out of the way (i.e. collide) when other nodes are dragged over them
margin={this.margin}
/>
-
</div>
</div >
);
}
-}
+} \ No newline at end of file
diff --git a/src/client/views/collections/collectionGrid/Grid.tsx b/src/client/views/collections/collectionGrid/Grid.tsx
index 6232fca7c..66edb99d9 100644
--- a/src/client/views/collections/collectionGrid/Grid.tsx
+++ b/src/client/views/collections/collectionGrid/Grid.tsx
@@ -1,7 +1,6 @@
import * as React from 'react';
import { observer } from "mobx-react";
-
import "../../../../../node_modules/react-grid-layout/css/styles.css";
import "../../../../../node_modules/react-resizable/css/styles.css";
@@ -29,7 +28,6 @@ interface GridProps {
*/
@observer
export default class Grid extends React.Component<GridProps> {
-
render() {
const compactType = this.props.compactType === "vertical" || this.props.compactType === "horizontal" ? this.props.compactType : null;
return (