aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--package.json1
-rw-r--r--src/client/documents/Documents.ts3
-rw-r--r--src/client/views/Templates.tsx10
-rw-r--r--src/client/views/collections/CollectionStackingView.scss7
-rw-r--r--src/client/views/collections/CollectionStackingView.tsx62
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss7
-rw-r--r--src/client/views/collections/collectionFreeForm/MarqueeView.tsx88
-rw-r--r--src/client/views/nodes/ImageBox.tsx2
8 files changed, 122 insertions, 58 deletions
diff --git a/package.json b/package.json
index d5abc808e..df0767b50 100644
--- a/package.json
+++ b/package.json
@@ -119,6 +119,7 @@
"html-to-image": "^0.1.0",
"i": "^0.3.6",
"image-data-uri": "^2.0.0",
+ "imagesloaded": "^4.1.4",
"jsonwebtoken": "^8.5.0",
"jsx-to-string": "^1.4.0",
"lodash": "^4.17.11",
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 1f4b76384..4bc0df31f 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 { UndoManager } from "../util/UndoManager";
+import { RouteStore } from "../../server/RouteStore";
var requestImageSize = require('request-image-size');
export interface DocumentOptions {
@@ -218,7 +219,7 @@ export namespace Docs {
export function ImageDocument(url: string, options: DocumentOptions = {}) {
let inst = CreateInstance(imageProto, new ImageField(new URL(url)), options);
- requestImageSize(url)
+ requestImageSize(window.origin + RouteStore.corsProxy + "/" + url)
.then((size: any) => {
if (!inst.proto!.nativeWidth) {
inst.proto!.nativeWidth = size.width;
diff --git a/src/client/views/Templates.tsx b/src/client/views/Templates.tsx
index 5a99b3d90..303f3f3b8 100644
--- a/src/client/views/Templates.tsx
+++ b/src/client/views/Templates.tsx
@@ -56,10 +56,12 @@ export namespace Templates {
</div>` );
export const Title = new Template("Title", TemplatePosition.InnerTop,
- `<div><div style="height:calc(100% - 25px); margin-top: 25px; width:100%;position:absolute;">{layout}</div>
- <div style="height:25px; width:100%; position:absolute; top: 0; background-color: rgba(0, 0, 0, .4); color: white; ">
- <span style="text-align:center;width:100%;font-size:20px;position:absolute;overflow:hidden;white-space:nowrap;text-overflow:ellipsis">{props.Document.title}</span>
- </div></div>` );
+ `<div>
+ <div style="height:calc(100% - 25px); margin-top: 25px; width:100%;position:absolute;">{layout}</div>
+ <div style="height:25px; width:100%; position:absolute; top: 0; background-color: rgba(0, 0, 0, .4); color: white; ">
+ <span style="text-align:center;width:100%;font-size:20px;position:absolute;overflow:hidden;white-space:nowrap;text-overflow:ellipsis">{props.Document.title}</span>
+ </div>
+ </div>` );
export const Bullet = new Template("Bullet", TemplatePosition.InnerTop,
`<div>
diff --git a/src/client/views/collections/CollectionStackingView.scss b/src/client/views/collections/CollectionStackingView.scss
index 803e680e5..6043a813d 100644
--- a/src/client/views/collections/CollectionStackingView.scss
+++ b/src/client/views/collections/CollectionStackingView.scss
@@ -31,6 +31,13 @@
align-items: center;
}
+ .collectionStackingview-masonryGrid {
+ display:grid;
+ width:100%;
+ height:100%;
+ position: absolute;
+ }
+
.collectionStackingView-description {
font-size: 100%;
margin-bottom: 1vw;
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index a1cb73123..a29648d5b 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -1,36 +1,76 @@
import React = require("react");
import { observer } from "mobx-react";
-import { CollectionSubView } from "./CollectionSubView";
-import Measure from "react-measure";
-import { Doc, WidthSym, HeightSym } from "../../../new_fields/Doc";
+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 { emptyFunction, returnOne } from "../../../Utils";
import "./CollectionStackingView.scss";
-import { runInAction, action, observable, computed } from "mobx";
-import { StrCast } from "../../../new_fields/Types";
+import { action, reaction } from "mobx";
+import { StrCast, NumCast } from "../../../new_fields/Types";
+import { Id } from "../../../new_fields/FieldSymbols";
+
+
@observer
export class CollectionStackingView extends CollectionSubView(doc => doc) {
getPreviewTransform = (): Transform => this.props.ScreenToLocalTransform();
+ 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
moveDocument = (doc: Doc, targetCollection: Doc, addDocument: (document: Doc) => boolean): boolean => {
this.props.removeDocument(doc);
addDocument(doc);
return true;
}
-
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)));
return (
- <div className="collectionStackingView" onWheel={(e: React.WheelEvent) => e.stopPropagation()}>
- <div className="collectionStackingView-description">{StrCast(this.props.Document.documentText, StrCast(this.props.Document.title, "stacking collection"))}</div>
- <div className="collectionStackingView-flexCont">
+ <div className="collectionStackingView" ref={this.createDropTarget} onWheel={(e: React.WheelEvent) => e.stopPropagation()}>
+ <div className="collectionStackingview-masonryGrid"
+ style={{
+ padding: `${topMargin}px 0px 0px ${leftMargin}px`,
+ width: `${cells * itemCols * (gridSize + gridGap) + leftMargin}`,
+ margin: "auto", position: "relative",
+ gridGap: gridGap,
+ gridTemplateColumns: `repeat(auto-fill, minmax(${gridSize}px,1fr))`,
+ gridAutoRows: `${gridSize}px`
+ }}
+ >
{docs.map(d => {
- return (<div className="collectionStackingView-docView-container">
+ let colSpan = Math.ceil((itemWidth + gridGap) / (gridSize + gridGap));
+ let rowSpan = Math.ceil((itemWidth / d[WidthSym]() * d[HeightSym]() + gridGap) / (gridSize + gridGap));
+ return (<div className="mycontent" id={StrCast(d.title, "")}
+ key={d[Id]}
+ style={{
+ transformOrigin: "top left",
+ gridRowEnd: `span ${rowSpan}`,
+ gridColumnEnd: `span ${colSpan}`,
+ transform: `scale(${itemWidth / NumCast(d.nativeWidth, 1)}, ${itemWidth / NumCast(d.nativeWidth, 1)})`
+ }} >
<DocumentView Document={d}
- addDocument={this.props.addDocument} removeDocument={this.props.removeDocument}
+ addDocument={this.props.addDocument}
+ removeDocument={this.props.removeDocument}
moveDocument={this.moveDocument}
ContainingCollectionView={this.props.CollectionView}
isTopMost={false}
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss
index 8557a3db4..e10ba9d7e 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss
@@ -25,6 +25,9 @@
height: 100%;
width: 100%;
}
+ >.jsx-parser {
+ z-index:0;
+ }
//nested freeform views
// .collectionfreeformview-container {
@@ -52,6 +55,10 @@
position: inherit;
height: 100%;
}
+
+ >.jsx-parser {
+ z-index:0;
+ }
.formattedTextBox-cont {
background: $light-color-secondary;
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index 973ebfbdd..64d5301c9 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -83,56 +83,62 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
});
})();
} else if (e.key === "b" && 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();
+ navigator.clipboard.readText().then(text => {
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 = "";
- let rowProto = new Doc();
- rowProto.title = rowProto.Id;
- rowProto.width = 200;
- rowProto.isPrototype = true;
- 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 docDataProto = Doc.MakeDelegate(rowProto);
- docDataProto.isPrototype = true;
- columns.forEach((col, i) => docDataProto[columns[i]] = (values.length > i ? ((values[i].indexOf(Number(values[i]).toString()) !== -1) ? Number(values[i]) : values[i]) : undefined));
- if (groupAttr) {
- docDataProto._group = groupAttr;
- }
- docDataProto.title = i.toString();
- let doc = Doc.MakeDelegate(docDataProto);
- doc.width = 200;
- docList.push(doc);
- }
- let newCol = Docs.SchemaDocument([...(groupAttr ? ["_group"] : []), ...columns.filter(c => c)], docList, { x: x, y: y, title: "droppedTable", width: 300, height: 100 });
-
- this.props.addDocument(newCol, false);
+ 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
+ } else {
+ this.pasteTable(ns, x, y);
}
- })();
+ });
} else {
let newBox = Docs.TextDocument({ width: 200, height: 100, x: x, y: y, title: "-typed text-" });
this.props.addLiveTextDocument(newBox);
}
e.stopPropagation();
}
+ //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
+ pasteTable(ns: string[], x: number, y: number) {
+ 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 = "";
+ let rowProto = new Doc();
+ rowProto.title = rowProto.Id;
+ rowProto.width = 200;
+ rowProto.isPrototype = true;
+ 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 docDataProto = Doc.MakeDelegate(rowProto);
+ docDataProto.isPrototype = true;
+ columns.forEach((col, i) => docDataProto[columns[i]] = (values.length > i ? ((values[i].indexOf(Number(values[i]).toString()) !== -1) ? Number(values[i]) : values[i]) : undefined));
+ if (groupAttr) {
+ docDataProto._group = groupAttr;
+ }
+ docDataProto.title = i.toString();
+ let doc = Doc.MakeDelegate(docDataProto);
+ doc.width = 200;
+ docList.push(doc);
+ }
+ let newCol = Docs.SchemaDocument([...(groupAttr ? ["_group"] : []), ...columns.filter(c => c)], docList, { x: x, y: y, title: "droppedTable", width: 300, height: 100 });
+
+ this.props.addDocument(newCol, false);
+ }
+ }
@action
onPointerDown = (e: React.PointerEvent): void => {
this._downX = this._lastX = e.pageX;
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index 128f3c6f8..d70068295 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -86,8 +86,8 @@ export class ImageBox extends DocComponent<FieldViewProps, ImageDocument>(ImageD
onPointerDown = (e: React.PointerEvent): void => {
if (e.shiftKey && e.ctrlKey)
- e.stopPropagation();
+ e.stopPropagation();
// if (Date.now() - this._lastTap < 300) {
// if (e.buttons === 1) {
// this._downX = e.clientX;