aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client/views/collections/CollectionMasonryViewFieldRow.tsx377
-rw-r--r--src/client/views/collections/CollectionStackingView.scss20
-rw-r--r--src/client/views/collections/CollectionStackingView.tsx104
-rw-r--r--src/client/views/collections/CollectionStackingViewFieldColumn.tsx1
-rw-r--r--src/client/views/collections/CollectionSubView.tsx4
5 files changed, 462 insertions, 44 deletions
diff --git a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx
new file mode 100644
index 000000000..f0d574132
--- /dev/null
+++ b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx
@@ -0,0 +1,377 @@
+import React = require("react");
+import { library } from '@fortawesome/fontawesome-svg-core';
+import { faPalette } from '@fortawesome/free-solid-svg-icons';
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import { action, observable } from "mobx";
+import { observer } from "mobx-react";
+import { Doc, WidthSym } from "../../../new_fields/Doc";
+import { Id } from "../../../new_fields/FieldSymbols";
+import { PastelSchemaPalette, SchemaHeaderField } from "../../../new_fields/SchemaHeaderField";
+import { ScriptField } from "../../../new_fields/ScriptField";
+import { NumCast, StrCast } from "../../../new_fields/Types";
+import { Utils, numberRange } from "../../../Utils";
+import { Docs } from "../../documents/Documents";
+import { DragManager } from "../../util/DragManager";
+import { CompileScript } from "../../util/Scripting";
+import { SelectionManager } from "../../util/SelectionManager";
+import { Transform } from "../../util/Transform";
+import { undoBatch } from "../../util/UndoManager";
+import { anchorPoints, Flyout } from "../DocumentDecorations";
+import { EditableView } from "../EditableView";
+import { CollectionStackingView } from "./CollectionStackingView";
+import "./CollectionStackingView.scss";
+
+library.add(faPalette);
+
+interface CMVFieldRowProps {
+ rows: () => number;
+ headings: () => object[];
+ heading: string;
+ headingObject: SchemaHeaderField | undefined;
+ docList: Doc[];
+ parent: CollectionStackingView;
+ type: "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" | undefined;
+ createDropTarget: (ele: HTMLDivElement) => void;
+ screenToLocalTransform: () => Transform;
+ color: string | undefined;
+}
+
+@observer
+export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowProps> {
+ @observable private _background = "inherit";
+
+ private _dropRef: HTMLDivElement | null = null;
+ private dropDisposer?: DragManager.DragDropDisposer;
+ private _headerRef: React.RefObject<HTMLDivElement> = React.createRef();
+ private _startDragPosition: { x: number, y: number } = { x: 0, y: 0 };
+ private _sensitivity: number = 16;
+
+ @observable _heading = this.props.headingObject ? this.props.headingObject.heading : this.props.heading;
+ @observable _color = this.props.headingObject ? this.props.headingObject.color : "#f1efeb";
+
+ createRowDropRef = (ele: HTMLDivElement | null) => {
+ this._dropRef = ele;
+ this.dropDisposer && this.dropDisposer();
+ if (ele) {
+ this.dropDisposer = DragManager.MakeDropTarget(ele, { handlers: { drop: this.rowDrop.bind(this) } });
+ }
+ }
+
+ @undoBatch
+ @action
+ rowDrop = (e: Event, de: DragManager.DropEvent) => {
+ if (de.data instanceof DragManager.DocumentDragData) {
+ let key = StrCast(this.props.parent.props.Document.sectionFilter);
+ let castedValue = this.getValue(this._heading);
+ if (castedValue) {
+ de.data.droppedDocuments.forEach(d => d[key] = castedValue);
+ }
+ else {
+ de.data.droppedDocuments.forEach(d => d[key] = undefined);
+ }
+ this.props.parent.drop(e, de);
+ e.stopPropagation();
+ }
+ }
+
+ masonryChildren(docs: Doc[]) {
+ let parent = this.props.parent;
+ parent._docXfs.length = 0;
+ return docs.map((d, i) => {
+ let dref = React.createRef<HTMLDivElement>();
+ let layoutDoc = Doc.expandTemplateLayout(d, parent.props.DataDoc);
+ let width = () => (d.nativeWidth && !d.ignoreAspect && !parent.props.Document.fillColumn ? Math.min(d[WidthSym](), parent.columnWidth) : parent.columnWidth);/// (uniqueHeadings.length + 1);
+ let height = () => parent.getDocHeight(layoutDoc);
+ let dxf = () => parent.getDocTransform(layoutDoc, dref.current!);
+ let rowSpan = Math.ceil((height() + parent.gridGap) / parent.gridGap);
+ parent._docXfs.push({ dxf: dxf, width: width, height: height });
+ return <div className="collectionStackingView-masonryDoc" key={d[Id]} ref={dref} style={{ gridRowEnd: `span ${rowSpan}` }} >
+ {this.props.parent.getDisplayDoc(layoutDoc, d, dxf, width)}
+ </div>;
+ });
+ }
+
+ getDocTransform(doc: Doc, dref: HTMLDivElement) {
+ let { scale, translateX, translateY } = Utils.GetScreenTransform(dref);
+ let outerXf = Utils.GetScreenTransform(this.props.parent._masonryGridRef!);
+ let offset = this.props.parent.props.ScreenToLocalTransform().transformDirection(outerXf.translateX - translateX, outerXf.translateY - translateY);
+ return this.props.parent.props.ScreenToLocalTransform().
+ translate(offset[0], offset[1]).
+ scale(NumCast(doc.width, 1) / this.props.parent.columnWidth);
+ }
+
+ getValue = (value: string): any => {
+ let parsed = parseInt(value);
+ if (!isNaN(parsed)) {
+ return parsed;
+ }
+ if (value.toLowerCase().indexOf("true") > -1) {
+ return true;
+ }
+ if (value.toLowerCase().indexOf("false") > -1) {
+ return false;
+ }
+ return value;
+ }
+
+ @action
+ headingChanged = (value: string, shiftDown?: boolean) => {
+ let key = StrCast(this.props.parent.props.Document.sectionFilter);
+ let castedValue = this.getValue(value);
+ if (castedValue) {
+ if (this.props.parent.sectionHeaders) {
+ if (this.props.parent.sectionHeaders.map(i => i.heading).indexOf(castedValue.toString()) > -1) {
+ return false;
+ }
+ }
+ this.props.docList.forEach(d => d[key] = castedValue);
+ if (this.props.headingObject) {
+ this.props.headingObject.setHeading(castedValue.toString());
+ this._heading = this.props.headingObject.heading;
+ }
+ return true;
+ }
+ return false;
+ }
+
+ @action
+ changeColumnColor = (color: string) => {
+ if (this.props.headingObject) {
+ this.props.headingObject.setColor(color);
+ this._color = color;
+ }
+ }
+
+ @action
+ pointerEntered = () => {
+ if (SelectionManager.GetIsDragging()) {
+ this._background = "#b4b4b4";
+ }
+ }
+
+ @action
+ pointerLeave = () => {
+ this._background = "inherit";
+ document.removeEventListener("pointermove", this.startDrag);
+ }
+
+ @action
+ addDocument = (value: string, shiftDown?: boolean) => {
+ let key = StrCast(this.props.parent.props.Document.sectionFilter);
+ let newDoc = Docs.Create.TextDocument({ height: 18, width: 200, title: value });
+ newDoc[key] = this.getValue(this.props.heading);
+ return this.props.parent.props.addDocument(newDoc);
+ }
+
+ @action
+ deleteColumn = () => {
+ let key = StrCast(this.props.parent.props.Document.sectionFilter);
+ this.props.docList.forEach(d => d[key] = undefined);
+ if (this.props.parent.sectionHeaders && this.props.headingObject) {
+ let index = this.props.parent.sectionHeaders.indexOf(this.props.headingObject);
+ this.props.parent.sectionHeaders.splice(index, 1);
+ }
+ }
+
+ startDrag = (e: PointerEvent) => {
+ let [dx, dy] = this.props.screenToLocalTransform().transformDirection(e.clientX - this._startDragPosition.x, e.clientY - this._startDragPosition.y);
+ if (Math.abs(dx) + Math.abs(dy) > this._sensitivity) {
+ let alias = Doc.MakeAlias(this.props.parent.props.Document);
+ let key = StrCast(this.props.parent.props.Document.sectionFilter);
+ let value = this.getValue(this._heading);
+ value = typeof value === "string" ? `"${value}"` : value;
+ let script = `return doc.${key} === ${value}`;
+ let compiled = CompileScript(script, { params: { doc: Doc.name } });
+ if (compiled.compiled) {
+ let scriptField = new ScriptField(compiled);
+ alias.viewSpecScript = scriptField;
+ let dragData = new DragManager.DocumentDragData([alias], [alias.proto]);
+ DragManager.StartDocumentDrag([this._headerRef.current!], dragData, e.clientX, e.clientY);
+ }
+
+ e.stopPropagation();
+ document.removeEventListener("pointermove", this.startDrag);
+ document.removeEventListener("pointerup", this.pointerUp);
+ }
+ }
+
+ pointerUp = (e: PointerEvent) => {
+ e.stopPropagation();
+ e.preventDefault();
+
+ document.removeEventListener("pointermove", this.startDrag);
+ document.removeEventListener("pointerup", this.pointerUp);
+ }
+
+ headerDown = (e: React.PointerEvent<HTMLDivElement>) => {
+ e.stopPropagation();
+ e.preventDefault();
+
+ let [dx, dy] = this.props.screenToLocalTransform().transformDirection(e.clientX, e.clientY);
+ this._startDragPosition = { x: dx, y: dy };
+
+ document.removeEventListener("pointermove", this.startDrag);
+ document.addEventListener("pointermove", this.startDrag);
+ document.removeEventListener("pointerup", this.pointerUp);
+ document.addEventListener("pointerup", this.pointerUp);
+ }
+
+ renderColorPicker = () => {
+ let selected = this.props.headingObject ? this.props.headingObject.color : "#f1efeb";
+
+ let pink = PastelSchemaPalette.get("pink2");
+ let purple = PastelSchemaPalette.get("purple4");
+ let blue = PastelSchemaPalette.get("bluegreen1");
+ let yellow = PastelSchemaPalette.get("yellow4");
+ let red = PastelSchemaPalette.get("red2");
+ let green = PastelSchemaPalette.get("bluegreen7");
+ let cyan = PastelSchemaPalette.get("bluegreen5");
+ let orange = PastelSchemaPalette.get("orange1");
+ let gray = "#f1efeb";
+
+ return (
+ <div className="collectionStackingView-colorPicker">
+ <div className="colorOptions">
+ <div className={"colorPicker" + (selected === pink ? " active" : "")} style={{ backgroundColor: pink }} onClick={() => this.changeColumnColor(pink!)}></div>
+ <div className={"colorPicker" + (selected === purple ? " active" : "")} style={{ backgroundColor: purple }} onClick={() => this.changeColumnColor(purple!)}></div>
+ <div className={"colorPicker" + (selected === blue ? " active" : "")} style={{ backgroundColor: blue }} onClick={() => this.changeColumnColor(blue!)}></div>
+ <div className={"colorPicker" + (selected === yellow ? " active" : "")} style={{ backgroundColor: yellow }} onClick={() => this.changeColumnColor(yellow!)}></div>
+ <div className={"colorPicker" + (selected === red ? " active" : "")} style={{ backgroundColor: red }} onClick={() => this.changeColumnColor(red!)}></div>
+ <div className={"colorPicker" + (selected === gray ? " active" : "")} style={{ backgroundColor: gray }} onClick={() => this.changeColumnColor(gray)}></div>
+ <div className={"colorPicker" + (selected === green ? " active" : "")} style={{ backgroundColor: green }} onClick={() => this.changeColumnColor(green!)}></div>
+ <div className={"colorPicker" + (selected === cyan ? " active" : "")} style={{ backgroundColor: cyan }} onClick={() => this.changeColumnColor(cyan!)}></div>
+ <div className={"colorPicker" + (selected === orange ? " active" : "")} style={{ backgroundColor: orange }} onClick={() => this.changeColumnColor(orange!)}></div>
+ </div>
+ </div>
+ );
+ }
+
+ @observable _headingsHack: number = 1;
+ render() {
+ let cols = this.props.rows();
+ let key = StrCast(this.props.parent.props.Document.sectionFilter);
+ let templatecols = "";
+ let headings = this.props.headings();
+ let heading = this._heading;
+ let style = this.props.parent;
+ let uniqueHeadings = headings.map((i, idx) => headings.indexOf(i) === idx);
+ let evContents = heading ? heading : this.props.type && this.props.type === "number" ? "0" : `NO ${key.toUpperCase()} VALUE`;
+ let headerEditableViewProps = {
+ GetValue: () => evContents,
+ SetValue: this.headingChanged,
+ contents: evContents,
+ oneLine: true
+ };
+ let newEditableViewProps = {
+ GetValue: () => "",
+ SetValue: this.addDocument,
+ contents: "+ NEW"
+ };
+ // let headingView = this.props.headingObject ?
+ let headingView =
+ <div>
+ <div key={`${this.props.heading}`} className="collectionStackingView-sectionHeader" style={{ background: this.props.color }}
+ // onClick={action(() => this._headingsHack++ && instHeading.setCollapsed(!instHeading.collapsed))}
+ >
+ {this.props.heading}
+ </div >
+ {/* <div className="red-box"></div> */}
+ <EditableView {...headerEditableViewProps} />
+ {evContents === `NO ${key.toUpperCase()} VALUE` ? (null) :
+ <div className="collectionStackingView-sectionColor">
+ <Flyout anchorPoint={anchorPoints.TOP_CENTER} content={this.renderColorPicker()}>
+ <button className="collectionStackingView-sectionColorButton">
+ <FontAwesomeIcon icon="palette" size="sm" />
+ </button>
+ </ Flyout >
+ </div>
+ }
+ </div>;
+
+
+ // <div key={heading} className="collectionStackingView-sectionHeader" ref={this._headerRef}
+ // style={{
+ // width: (style.columnWidth) /
+ // ((uniqueHeadings.length +
+ // ((this.props.parent.props.CollectionView.props.Document.chromeStatus !== 'view-mode' && this.props.parent.props.CollectionView.props.Document.chromeStatus !== 'disabled') ? 1 : 0)) || 1)
+ // }}>
+ // {/* the default bucket (no key value) has a tooltip that describes what it is.
+ // Further, it does not have a color and cannot be deleted. */}
+ // <div className="collectionStackingView-sectionHeader-subCont" onPointerDown={this.headerDown}
+ // title={evContents === `NO ${key.toUpperCase()} VALUE` ?
+ // `Documents that don't have a ${key} value will go here. This column cannot be removed.` : ""}
+ // style={{
+ // width: "100%",
+ // background: evContents !== `NO ${key.toUpperCase()} VALUE` ? this._color : "lightgrey",
+ // color: "grey"
+ // }}>
+ // <EditableView {...headerEditableViewProps} />
+ // {evContents === `NO ${key.toUpperCase()} VALUE` ? (null) :
+ // <div className="collectionStackingView-sectionColor">
+ // <Flyout anchorPoint={anchorPoints.TOP_CENTER} content={this.renderColorPicker()}>
+ // <button className="collectionStackingView-sectionColorButton">
+ // <FontAwesomeIcon icon="palette" size="sm" />
+ // </button>
+ // </ Flyout >
+ // </div>
+ // }
+ // {evContents === `NO ${key.toUpperCase()} VALUE` ?
+ // (null) :
+ // <button className="collectionStackingView-sectionDelete" onClick={this.deleteColumn}>
+ // <FontAwesomeIcon icon="trash" />
+ // </button>}
+ // </div>;
+ // </div> : (null);
+ // for (let i = 0; i < cols; i++) templatecols += `${style.columnWidth / style.numGroupColumns}px `;
+ return (
+ <div className="collectionStackingView-masonrySection"
+ key={heading = "empty"}
+ style={{ width: `${100 / ((uniqueHeadings.length + ((this.props.parent.props.CollectionView.props.Document.chromeStatus !== 'view-mode' && this.props.parent.props.CollectionView.props.Document.chromeStatus !== 'disabled') ? 1 : 0)) || 1)}%`, background: this._background }}
+ ref={this.createRowDropRef} onPointerEnter={this.pointerEntered} onPointerLeave={this.pointerLeave} >
+ {headingView}
+ {/* {!heading ? (null) :
+ <div key={`${instHeading.heading}`} className="collectionStackingView-sectionHeader" style={{ background: instHeading.color }}
+ onClick={action(() => this._headingsHack++ && instHeading.setCollapsed(!instHeading.collapsed))} >
+ {instHeading.heading}
+ </div>} */}
+ {/* <div key={`${heading}-stack`} className={`collectionStackingView-masonry${singleColumn ? "Single" : "Grid"}`}
+ style={{
+ padding: singleColumn ? `${style.yMargin}px ${0}px ${style.yMargin}px ${0}px` : `${style.yMargin}px ${0}px`,
+ margin: "auto",
+ width: "max-content", //singleColumn ? undefined : `${cols * (style.columnWidth + style.gridGap) + 2 * style.xMargin - style.gridGap}px`,
+ height: 'max-content',
+ position: "relative",
+ gridGap: style.gridGap,
+ gridTemplateColumns: singleColumn ? undefined : templatecols,
+ gridAutoRows: singleColumn ? undefined : "0px"
+ }}
+ // ref={this.createColumnDropRef} onPointerEnter={this.pointerEntered} onPointerLeave={this.pointerLeave}
+ >
+ {this.masonryChildren(this.props.docList)}
+ {singleColumn ? (null) : this.props.parent.columnDragger}
+ </div> */}
+ {
+ this._headingsHack && heading ? (null) :
+ <div key={`${heading}-stack`} className={`collectionStackingView-masonryGrid`}
+ style={{
+ padding: `${this.props.parent.yMargin}px ${this.props.parent.xMargin}px`,
+ width: `${cols * (this.props.parent.columnWidth + this.props.parent.gridGap) + 2 * this.props.parent.xMargin - this.props.parent.gridGap}px`,
+ gridGap: this.props.parent.gridGap,
+ // gridTemplateColumns: undefined,
+ gridTemplateColumns: numberRange(cols).reduce((list: string, i: any) => list + ` ${this.props.parent.columnWidth}px`, ""),
+ }}>
+ {this.masonryChildren(this.props.docList)}
+ {this.props.parent.columnDragger}
+ </div>
+ }
+ { //controls the +NEW for each row
+ (this.props.parent.props.CollectionView.props.Document.chromeStatus !== 'view-mode' && this.props.parent.props.CollectionView.props.Document.chromeStatus !== 'disabled') ?
+ <div key={`${heading}-add-document`} className="collectionStackingView-addDocumentButton"
+ style={{ width: style.columnWidth / style.numGroupColumns }}>
+ <EditableView {...newEditableViewProps} />
+ </div> : null
+ }
+ </div >
+ );
+ }
+} \ No newline at end of file
diff --git a/src/client/views/collections/CollectionStackingView.scss b/src/client/views/collections/CollectionStackingView.scss
index 01d4ea2b6..a83c97624 100644
--- a/src/client/views/collections/CollectionStackingView.scss
+++ b/src/client/views/collections/CollectionStackingView.scss
@@ -1,12 +1,15 @@
@import "../globalCssVariables";
.collectionMasonryView {
- display:inline;
+ display: inline;
}
-.collectionStackingView{
+
+.collectionStackingView {
display: flex;
}
-.collectionStackingView, .collectionMasonryView{
+
+.collectionStackingView,
+.collectionMasonryView {
height: 100%;
width: 100%;
position: absolute;
@@ -14,6 +17,7 @@
overflow-y: auto;
flex-wrap: wrap;
transition: top .5s;
+
.collectionSchemaView-previewDoc {
height: 100%;
position: absolute;
@@ -40,10 +44,12 @@
top: 0;
left: 0;
}
+
.collectionStackingView-masonrySingle {
height: 100%;
position: absolute;
}
+
.collectionStackingView-masonryGrid {
margin: auto;
height: max-content;
@@ -91,7 +97,7 @@
height: 100%;
margin: auto;
}
-
+
.collectionStackingView-masonrySection {
margin: auto;
}
@@ -290,4 +296,10 @@
}
+}
+
+.red-box {
+ width: 200px;
+ height: 200px;
+ background: red;
} \ No newline at end of file
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index 2e4f6aff5..c2342eb50 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -23,6 +23,7 @@ import { CollectionSubView } from "./CollectionSubView";
import { ContextMenu } from "../ContextMenu";
import { ContextMenuProps } from "../ContextMenuItem";
import { ScriptBox } from "../ScriptBox";
+import { CollectionMasonryViewFieldRow } from "./CollectionMasonryViewFieldRow";
@observer
export class CollectionStackingView extends CollectionSubView(doc => doc) {
@@ -125,7 +126,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
}
createRef = (ele: HTMLDivElement | null) => {
this._masonryGridRef = ele;
- this.createDropTarget(ele!);
+ this.createDropTarget(ele!); //so the whole grid is the drop target?
}
overlays = (doc: Doc) => {
@@ -282,45 +283,72 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
translate(offset[0], offset[1]).
scale(NumCast(doc.width, 1) / this.columnWidth);
}
- masonryChildren(docs: Doc[]) {
- this._docXfs.length = 0;
- return docs.map((d, i) => {
- let dref = React.createRef<HTMLDivElement>();
- let layoutDoc = Doc.expandTemplateLayout(d, this.props.DataDoc);
- let width = () => (d.nativeWidth && !d.ignoreAspect && !this.props.Document.fillColumn ? Math.min(d[WidthSym](), this.columnWidth) : this.columnWidth);/// (uniqueHeadings.length + 1);
- let height = () => this.getDocHeight(layoutDoc);
- let dxf = () => this.getDocTransform(layoutDoc, dref.current!);
- let rowSpan = Math.ceil((height() + this.gridGap) / this.gridGap);
- this._docXfs.push({ dxf: dxf, width: width, height: height });
- return <div className="collectionStackingView-masonryDoc" key={d[Id]} ref={dref} style={{ gridRowEnd: `span ${rowSpan}` }} >
- {this.getDisplayDoc(layoutDoc, d, dxf, width)}
- </div>;
- });
- }
+ // masonryChildren(docs: Doc[]) {
+ // this._docXfs.length = 0;
+ // return docs.map((d, i) => {
+ // let dref = React.createRef<HTMLDivElement>();
+ // let layoutDoc = Doc.expandTemplateLayout(d, this.props.DataDoc);
+ // let width = () => (d.nativeWidth && !d.ignoreAspect && !this.props.Document.fillColumn ? Math.min(d[WidthSym](), this.columnWidth) : this.columnWidth);/// (uniqueHeadings.length + 1);
+ // let height = () => this.getDocHeight(layoutDoc);
+ // let dxf = () => this.getDocTransform(layoutDoc, dref.current!);
+ // let rowSpan = Math.ceil((height() + this.gridGap) / this.gridGap);
+ // this._docXfs.push({ dxf: dxf, width: width, height: height });
+ // return <div className="collectionStackingView-masonryDoc" key={d[Id]} ref={dref} style={{ gridRowEnd: `span ${rowSpan}` }} >
+ // {this.getDisplayDoc(layoutDoc, d, dxf, width)}
+ // </div>;
+ // });
+ // }
+
+ // @observable _headingsHack: number = 1;
+ // sectionMasonry(heading: SchemaHeaderField | undefined, docList: Doc[]) {
+ // let cols = Math.max(1, Math.min(docList.length,
+ // Math.floor((this.props.PanelWidth() - 2 * this.xMargin) / (this.columnWidth + this.gridGap))));
+ // // let specialCols = () => this.isMasonryView ? 1 : Math.max(1, Math.min(docList.length,
+ // // Math.floor((this.props.PanelWidth() - 2 * this.xMargin) / (this.columnWidth + this.gridGap))));
+ // // let type: "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" | undefined = undefined;
+ // return <div ref={} key={heading ? heading.heading : "empty"} className="collectionStackingView-masonrySection">
+ // {!heading ? (null) :
+ // <div key={`${heading.heading}`} className="collectionStackingView-sectionHeader" style={{ background: heading.color }}
+ // onClick={action(() => this._headingsHack++ && heading.setCollapsed(!heading.collapsed))} >
+ // {heading.heading}
+ // </div>}
+ // {this._headingsHack && heading && heading.collapsed ? (null) :
+ // <div key={`${heading}-stack`} className={`collectionStackingView-masonryGrid`}
+ // style={{
+ // padding: `${this.yMargin}px ${this.xMargin}px`,
+ // width: `${cols * (this.columnWidth + this.gridGap) + 2 * this.xMargin - this.gridGap}px`,
+ // gridGap: this.gridGap,
+ // gridTemplateColumns: numberRange(cols).reduce((list, i) => list + ` ${this.columnWidth}px`, ""),
+ // }}>
+ // {this.masonryChildren(docList)}
+ // {this.columnDragger}
+ // </div>
+ // }
+ // </div>;
+ // }
- @observable _headingsHack: number = 1;
- sectionMasonry(heading: SchemaHeaderField | undefined, docList: Doc[]) {
- let cols = Math.max(1, Math.min(docList.length,
+ sectionMasonry = (heading: SchemaHeaderField | undefined, docList: Doc[]) => {
+ let key = this.sectionFilter;
+ let type: "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" | undefined = undefined;
+ let types = docList.length ? docList.map(d => typeof d[key]) : this.childDocs.map(d => typeof d[key]);
+ if (types.map((i, idx) => types.indexOf(i) === idx).length === 1) {
+ type = types[0];
+ }
+ let rows = () => !this.isStackingView ? 1 : Math.max(1, Math.min(docList.length,
Math.floor((this.props.PanelWidth() - 2 * this.xMargin) / (this.columnWidth + this.gridGap))));
- return <div key={heading ? heading.heading : "empty"} className="collectionStackingView-masonrySection">
- {!heading ? (null) :
- <div key={`${heading.heading}`} className="collectionStackingView-sectionHeader" style={{ background: heading.color }}
- onClick={action(() => this._headingsHack++ && heading.setCollapsed(!heading.collapsed))} >
- {heading.heading}
- </div>}
- {this._headingsHack && heading && heading.collapsed ? (null) :
- <div key={`${heading}-stack`} className={`collectionStackingView-masonryGrid`}
- style={{
- padding: `${this.yMargin}px ${this.xMargin}px`,
- width: `${cols * (this.columnWidth + this.gridGap) + 2 * this.xMargin - this.gridGap}px`,
- gridGap: this.gridGap,
- gridTemplateColumns: numberRange(cols).reduce((list, i) => list + ` ${this.columnWidth}px`, ""),
- }}>
- {this.masonryChildren(docList)}
- {this.columnDragger}
- </div>
- }
- </div>;
+ return <CollectionMasonryViewFieldRow
+ key={heading ? heading.heading : ""}
+ rows={rows}
+ headings={this.headings}
+ heading={heading ? heading.heading : ""}
+ headingObject={heading}
+ docList={docList}
+ parent={this}
+ type={type}
+ createDropTarget={this.createDropTarget}
+ screenToLocalTransform={this.props.ScreenToLocalTransform}
+ color={heading ? heading.color : ""}
+ />;
}
@action
diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
index 74c7ef305..a3db46584 100644
--- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
+++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
@@ -318,6 +318,7 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
gridTemplateColumns: singleColumn ? undefined : templatecols,
gridAutoRows: singleColumn ? undefined : "0px"
}}
+ // ref={this.createColumnDropRef} onPointerEnter={this.pointerEntered} onPointerLeave={this.pointerLeave}
>
{this.children(this.props.docList)}
{singleColumn ? (null) : this.props.parent.columnDragger}
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index 077f3f941..ff0c76932 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -38,13 +38,13 @@ export interface SubCollectionViewProps extends CollectionViewProps {
export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) {
class CollectionSubView extends DocComponent<SubCollectionViewProps, T>(schemaCtor) {
private dropDisposer?: DragManager.DragDropDisposer;
- protected createDropTarget = (ele: HTMLDivElement) => {
+ protected createDropTarget = (ele: HTMLDivElement) => { //used for stacking and masonry view
this.dropDisposer && this.dropDisposer();
if (ele) {
this.dropDisposer = DragManager.MakeDropTarget(ele, { handlers: { drop: this.drop.bind(this) } });
}
}
- protected CreateDropTarget(ele: HTMLDivElement) {
+ protected CreateDropTarget(ele: HTMLDivElement) { //used in schema view
this.createDropTarget(ele);
}