aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/collections/CollectionSubView.tsx
diff options
context:
space:
mode:
authorMohammad Amoush <47069173+mamoush34@users.noreply.github.com>2020-02-08 17:03:12 -0500
committerMohammad Amoush <47069173+mamoush34@users.noreply.github.com>2020-02-08 17:03:12 -0500
commitf9855e8d1ec83405ae3cc7d0113b46de63fc0848 (patch)
treebf4be61a021e59b771c1cd5958fd9fd43cac8693 /src/client/views/collections/CollectionSubView.tsx
parent87f5f043388b591c52e96a795fa461a79770550d (diff)
parent1b046f76cf39f1f6cb1875aa84b45db74b6d994e (diff)
Merge branch 'master' of https://github.com/browngraphicslab/Dash-Web into webcam_mohammad
Diffstat (limited to 'src/client/views/collections/CollectionSubView.tsx')
-rw-r--r--src/client/views/collections/CollectionSubView.tsx94
1 files changed, 64 insertions, 30 deletions
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index 5753dd34e..62b9e8380 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -1,4 +1,4 @@
-import { action, computed, IReactionDisposer, reaction } from "mobx";
+import { action, computed, IReactionDisposer, reaction, trace } from "mobx";
import * as rp from 'request-promise';
import CursorField from "../../../new_fields/CursorField";
import { Doc, DocListCast, Opt } from "../../../new_fields/Doc";
@@ -23,6 +23,8 @@ import { basename } from 'path';
import { GooglePhotos } from "../../apis/google_docs/GooglePhotosClientUtils";
import { ImageUtils } from "../../util/Import & Export/ImageUtils";
import { Networking } from "../../Network";
+import { GestureUtils } from "../../../pen-gestures/GestureUtils";
+import { InteractionUtils } from "../../util/InteractionUtils";
export interface CollectionViewProps extends FieldViewProps {
addDocument: (document: Doc) => boolean;
@@ -38,56 +40,69 @@ export interface CollectionViewProps extends FieldViewProps {
export interface SubCollectionViewProps extends CollectionViewProps {
CollectionView: Opt<CollectionView>;
- ruleProvider: Doc | undefined;
children?: never | (() => JSX.Element[]) | React.ReactNode;
isAnnotationOverlay?: boolean;
annotationsKey: string;
+ layoutEngine?: () => string;
}
export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) {
class CollectionSubView extends DocComponent<SubCollectionViewProps, T>(schemaCtor) {
private dropDisposer?: DragManager.DragDropDisposer;
+ private gestureDisposer?: GestureUtils.GestureEventDisposer;
+ protected multiTouchDisposer?: InteractionUtils.MultiTouchEventDisposer;
private _childLayoutDisposer?: IReactionDisposer;
- protected createDropTarget = (ele: HTMLDivElement) => { //used for stacking and masonry view
- this.dropDisposer && this.dropDisposer();
+ protected createDashEventsTarget = (ele: HTMLDivElement) => { //used for stacking and masonry view
+ this.dropDisposer?.();
+ this.gestureDisposer?.();
+ this.multiTouchDisposer?.();
if (ele) {
this.dropDisposer = DragManager.MakeDropTarget(ele, this.drop.bind(this));
+ this.gestureDisposer = GestureUtils.MakeGestureTarget(ele, this.onGesture.bind(this));
+ this.multiTouchDisposer = InteractionUtils.MakeMultiTouchTarget(ele, this.onTouchStart.bind(this));
}
}
protected CreateDropTarget(ele: HTMLDivElement) { //used in schema view
- this.createDropTarget(ele);
+ this.createDashEventsTarget(ele);
}
componentDidMount() {
- this._childLayoutDisposer = reaction(() => [this.childDocs, Cast(this.props.Document.childLayout, Doc)],
- async (args) => {
- if (args[1] instanceof Doc) {
- this.childDocs.map(async doc => !Doc.AreProtosEqual(args[1] as Doc, (await doc).layout as Doc) && Doc.ApplyTemplateTo(args[1] as Doc, (await doc), "layoutFromParent"));
+ this._childLayoutDisposer = reaction(() => [this.childDocs, (Cast(this.props.Document.childLayout, Doc) as Doc)?.[Id]],
+ (args) => {
+ const childLayout = Cast(this.props.Document.childLayout, Doc);
+ if (childLayout instanceof Doc) {
+ this.childDocs.map(doc => {
+ doc.layout_fromParent = childLayout;
+ doc.layoutKey = "layout_fromParent";
+ });
}
- else if (!(args[1] instanceof Promise)) {
- this.childDocs.filter(d => !d.isTemplateField).map(async doc => doc.layoutKey === "layoutFromParent" && (doc.layoutKey = "layout"));
+ else if (!(childLayout instanceof Promise)) {
+ this.childDocs.filter(d => !d.isTemplateForField).map(doc => doc.layoutKey === "layout_fromParent" && (doc.layoutKey = "layout"));
}
- });
+ }, { fireImmediately: true });
}
componentWillUnmount() {
this._childLayoutDisposer && this._childLayoutDisposer();
}
- @computed get dataDoc() { return this.props.DataDoc && this.props.Document.isTemplateField ? Doc.GetProto(this.props.DataDoc) : Doc.GetProto(this.props.Document); }
- @computed get extensionDoc() { return Doc.fieldExtensionDoc(this.dataDoc, this.props.fieldKey); }
+ @computed get dataDoc() { return this.props.DataDoc && this.props.Document.isTemplateForField ? Doc.GetProto(this.props.DataDoc) : Doc.GetProto(this.props.Document); }
// The data field for rendering this collection will be on the this.props.Document unless we're rendering a template in which case we try to use props.DataDoc.
// When a document has a DataDoc but it's not a template, then it contains its own rendering data, but needs to pass the DataDoc through
// to its children which may be templates.
// If 'annotationField' is specified, then all children exist on that field of the extension document, otherwise, they exist directly on the data document under 'fieldKey'
@computed get dataField() {
- return this.props.annotationsKey ? (this.extensionDoc ? this.extensionDoc[this.props.annotationsKey] : undefined) : this.dataDoc[this.props.fieldKey];
+ const { annotationsKey, fieldKey } = this.props;
+ if (annotationsKey) {
+ return this.dataDoc[fieldKey + "-" + annotationsKey];
+ }
+ return this.dataDoc[fieldKey];
}
get childLayoutPairs(): { layout: Doc; data: Doc; }[] {
- const { Document, DataDoc, fieldKey } = this.props;
- const validPairs = this.childDocs.map(doc => Doc.GetLayoutDataDocPair(Document, DataDoc, fieldKey, doc)).filter(pair => pair.layout);
+ const { Document, DataDoc } = this.props;
+ const validPairs = this.childDocs.map(doc => Doc.GetLayoutDataDocPair(Document, !this.props.annotationsKey ? DataDoc : undefined, doc)).filter(pair => pair.layout);
return validPairs.map(({ data, layout }) => ({ data: data!, layout: layout! })); // this mapping is a bit of a hack to coerce types
}
get childDocList() {
@@ -132,6 +147,11 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) {
}
@undoBatch
+ protected onGesture(e: Event, ge: GestureUtils.GestureEvent) {
+
+ }
+
+ @undoBatch
@action
protected drop(e: Event, de: DragManager.DropEvent): boolean {
const docDragData = de.complete.docDragData;
@@ -139,8 +159,10 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) {
this.props.Document.dropConverter.script.run({ dragData: docDragData }); /// bcz: check this
if (docDragData && !docDragData.applyAsTemplate) {
if (de.altKey && docDragData.draggedDocuments.length) {
- this.childDocs.map(doc =>
- Doc.ApplyTemplateTo(docDragData.draggedDocuments[0], doc, "layoutFromParent"));
+ this.childDocs.map(doc => {
+ doc.layout_fromParent = docDragData.draggedDocuments[0];
+ doc.layoutKey = "layout_fromParent";
+ });
e.stopPropagation();
return true;
}
@@ -196,7 +218,7 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) {
this.props.addDocument && this.props.addDocument(Docs.Create.WebDocument(href, { ...options, title: href }));
}
} else if (text) {
- this.props.addDocument && this.props.addDocument(Docs.Create.TextDocument({ ...options, width: 100, height: 25, documentText: "@@@" + text }));
+ this.props.addDocument && this.props.addDocument(Docs.Create.TextDocument(text, { ...options, _width: 100, _height: 25 }));
}
return;
}
@@ -206,7 +228,12 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) {
const img = tags[0].startsWith("img") ? tags[0] : tags.length > 1 && tags[1].startsWith("img") ? tags[1] : "";
if (img) {
const split = img.split("src=\"")[1].split("\"")[0];
- const doc = Docs.Create.ImageDocument(split, { ...options, width: 300 });
+ let source = split;
+ if (split.startsWith("data:image") && split.includes("base64")) {
+ const [{ clientAccessPath }] = await Networking.PostToServer("/uploadRemoteImage", { sources: [split] });
+ source = Utils.prepend(clientAccessPath);
+ }
+ const doc = Docs.Create.ImageDocument(source, { ...options, _width: 300 });
ImageUtils.ExtractExif(doc);
this.props.addDocument(doc);
return;
@@ -221,7 +248,7 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) {
}
});
} else {
- const htmlDoc = Docs.Create.HtmlDocument(html, { ...options, title: "-web page-", width: 300, height: 300, documentText: text });
+ const htmlDoc = Docs.Create.HtmlDocument(html, { ...options, title: "-web page-", _width: 300, _height: 300, documentText: text });
this.props.addDocument(htmlDoc);
}
return;
@@ -229,12 +256,12 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) {
}
if (text && text.indexOf("www.youtube.com/watch") !== -1) {
const url = text.replace("youtube.com/watch?v=", "youtube.com/embed/");
- this.props.addDocument(Docs.Create.VideoDocument(url, { ...options, title: url, width: 400, height: 315, nativeWidth: 600, nativeHeight: 472.5 }));
+ this.props.addDocument(Docs.Create.VideoDocument(url, { ...options, title: url, _width: 400, _height: 315, _nativeWidth: 600, _nativeHeight: 472.5 }));
return;
}
let matches: RegExpExecArray | null;
if ((matches = /(https:\/\/)?docs\.google\.com\/document\/d\/([^\\]+)\/edit/g.exec(text)) !== null) {
- const newBox = Docs.Create.TextDocument({ ...options, width: 400, height: 200, title: "Awaiting title from Google Docs..." });
+ const newBox = Docs.Create.TextDocument("", { ...options, _width: 400, _height: 200, title: "Awaiting title from Google Docs..." });
const proto = newBox.proto!;
const documentId = matches[2];
proto[GoogleRef] = documentId;
@@ -281,13 +308,20 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) {
formData.append('file', file);
const dropFileName = file ? file.name : "-empty-";
- promises.push(Networking.PostFormDataToServer("/upload", formData).then(results => {
- results.map(action(({ clientAccessPath }: any) => {
- const full = { ...options, width: 300, title: dropFileName };
+ promises.push(Networking.PostFormDataToServer("/uploadFormData", formData).then(results => {
+ results.map(action((result: any) => {
+ const { clientAccessPath, nativeWidth, nativeHeight, contentSize } = result;
+ const full = { ...options, _width: 300, title: dropFileName };
const pathname = Utils.prepend(clientAccessPath);
Docs.Get.DocumentFromType(type, pathname, full).then(doc => {
- doc && (Doc.GetProto(doc).fileUpload = basename(pathname).replace("upload_", "").replace(/\.[a-z0-9]*$/, ""));
- doc && this.props.addDocument(doc);
+ if (doc) {
+ const proto = Doc.GetProto(doc);
+ proto.fileUpload = basename(pathname).replace("upload_", "").replace(/\.[a-z0-9]*$/, "");
+ nativeWidth && (proto["data-nativeWidth"] = nativeWidth);
+ nativeHeight && (proto["data-nativeHeight"] = nativeHeight);
+ contentSize && (proto.contentSize = contentSize);
+ this.props?.addDocument(doc);
+ }
});
}));
}));
@@ -298,7 +332,7 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) {
Promise.all(promises).finally(() => { completed && completed(); batch.end(); });
} else {
if (text && !text.includes("https://")) {
- this.props.addDocument(Docs.Create.TextDocument({ ...options, documentText: "@@@" + text, width: 400, height: 315 }));
+ this.props.addDocument(Docs.Create.TextDocument(text, { ...options, _width: 400, _height: 315 }));
}
batch.end();
}