diff options
| author | Brandon <brandon_li@brown.edu> | 2019-03-11 18:27:22 -0400 |
|---|---|---|
| committer | Brandon <brandon_li@brown.edu> | 2019-03-11 18:27:22 -0400 |
| commit | c1d2a28123f4c9290fe8346730976687671f4042 (patch) | |
| tree | 7d6ad3ca7c8216947ec7563963a55a5b9c39d848 /src/client/views/collections | |
| parent | c9ae6d447c151ffbc6691a095802489038d004c1 (diff) | |
| parent | 618e66a5a070f1aac9224bd3f44b76a5ac314bfa (diff) | |
Merge branch 'master' of https://github.com/browngraphicslab/Dash-Web into kvp
Diffstat (limited to 'src/client/views/collections')
7 files changed, 311 insertions, 121 deletions
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index c51fba908..6a0404663 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -35,6 +35,7 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp private _goldenLayout: any = null; private _containerRef = React.createRef<HTMLDivElement>(); private _fullScreen: any = null; + private _flush: boolean = false; constructor(props: SubCollectionViewProps) { super(props); @@ -43,7 +44,7 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp (window as any).ReactDOM = ReactDOM; } public StartOtherDrag(dragDoc: Document, e: any) { - this.AddRightSplit(dragDoc, true).contentItems[0].tab._dragListener.onMouseDown({ pageX: e.pageX, pageY: e.pageY, preventDefault: () => { }, button: e.button }) + this.AddRightSplit(dragDoc, true).contentItems[0].tab._dragListener.onMouseDown({ pageX: e.pageX, pageY: e.pageY, preventDefault: () => { }, button: 0 }) } @action @@ -164,7 +165,6 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp this._goldenLayout.updateSize(cur!.getBoundingClientRect().width, cur!.getBoundingClientRect().height); } - _flush: boolean = false; @action onPointerUp = (e: React.PointerEvent): void => { if (this._flush) { @@ -174,17 +174,12 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp } @action onPointerDown = (e: React.PointerEvent): void => { - if (e.button === 2 && this.props.active()) { + var className = (e.target as any).className; + if (className == "lm_drag_handle" || className == "lm_close" || className == "lm_maximise" || className == "lm_minimise" || className == "lm_close_tab") { + this._flush = true; + } + if (this.props.active()) { e.stopPropagation(); - e.preventDefault(); - } else { - var className = (e.target as any).className; - if (className == "lm_drag_handle" || className == "lm_close" || className == "lm_maximise" || className == "lm_minimise" || className == "lm_close_tab") { - this._flush = true; - } - if (e.buttons === 1 && this.props.active()) { - e.stopPropagation(); - } } } diff --git a/src/client/views/collections/CollectionFreeFormView.scss b/src/client/views/collections/CollectionFreeFormView.scss index f432e8cc3..d487cd7ce 100644 --- a/src/client/views/collections/CollectionFreeFormView.scss +++ b/src/client/views/collections/CollectionFreeFormView.scss @@ -1,8 +1,9 @@ .collectionfreeformview-container { - .collectionfreeformview > .jsx-parser{ + .collectionfreeformview > .jsx-parser{ position:absolute; height: 100%; + width: 100%; } border-style: solid; @@ -18,7 +19,40 @@ top: 0; left: 0; width:100%; - height: 100% + height: 100%; + } +} +.collectionfreeformview-marquee{ + border-style: dashed; + box-sizing: border-box; + position: absolute; + border-width: 1px; + border-color: black; +} +.collectionfreeformview-overlay { + + .collectionfreeformview > .jsx-parser{ + position:absolute; + height: 100%; + } + .formattedTextBox-cont { + background:yellow; + } + + border-style: solid; + box-sizing: border-box; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + overflow: hidden; + .collectionfreeformview { + position: absolute; + top: 0; + left: 0; + width:100%; + height: 100%; } } diff --git a/src/client/views/collections/CollectionFreeFormView.tsx b/src/client/views/collections/CollectionFreeFormView.tsx index f71f2791c..b0cd7e017 100644 --- a/src/client/views/collections/CollectionFreeFormView.tsx +++ b/src/client/views/collections/CollectionFreeFormView.tsx @@ -1,33 +1,39 @@ -import { observable, action, computed } from "mobx"; +import { action, computed, observable } from "mobx"; import { observer } from "mobx-react"; import { Document } from "../../../fields/Document"; import { FieldWaiting } from "../../../fields/Field"; import { KeyStore } from "../../../fields/KeyStore"; import { ListField } from "../../../fields/ListField"; import { TextField } from "../../../fields/TextField"; +import { Documents } from "../../documents/Documents"; import { DragManager } from "../../util/DragManager"; import { Transform } from "../../util/Transform"; import { undoBatch } from "../../util/UndoManager"; import { CollectionDockingView } from "../collections/CollectionDockingView"; +import { CollectionPDFView } from "../collections/CollectionPDFView"; import { CollectionSchemaView } from "../collections/CollectionSchemaView"; import { CollectionView } from "../collections/CollectionView"; +import { InkingCanvas } from "../InkingCanvas"; import { CollectionFreeFormDocumentView } from "../nodes/CollectionFreeFormDocumentView"; import { DocumentView } from "../nodes/DocumentView"; import { FormattedTextBox } from "../nodes/FormattedTextBox"; import { ImageBox } from "../nodes/ImageBox"; +import { KeyValueBox } from "../nodes/KeyValueBox"; +import { PDFBox } from "../nodes/PDFBox"; import { WebBox } from "../nodes/WebBox"; -import { KeyValueBox } from "../nodes/KeyValueBox" import "./CollectionFreeFormView.scss"; import { COLLECTION_BORDER_WIDTH } from "./CollectionView"; import { CollectionViewBase } from "./CollectionViewBase"; -import { Documents } from "../../documents/Documents"; import React = require("react"); +import { SelectionManager } from "../../util/SelectionManager"; const JsxParser = require('react-jsx-parser').default;//TODO Why does this need to be imported like this? @observer export class CollectionFreeFormView extends CollectionViewBase { private _canvasRef = React.createRef<HTMLDivElement>(); + @observable private _lastX: number = 0; + @observable private _lastY: number = 0; private _selectOnLoaded: string = ""; // id of document that should be selected once it's loaded (used for click-to-type) @@ -56,18 +62,23 @@ export class CollectionFreeFormView extends CollectionViewBase { super.drop(e, de); const docView: DocumentView = de.data["documentView"]; let doc: Document = docView ? docView.props.Document : de.data["document"]; - let screenX = de.x - (de.data["xOffset"] as number || 0); - let screenY = de.y - (de.data["yOffset"] as number || 0); - const [x, y] = this.getTransform().transformPoint(screenX, screenY); - doc.SetNumber(KeyStore.X, x); - doc.SetNumber(KeyStore.Y, y); - this.bringToFront(doc); + if (doc) { + let screenX = de.x - (de.data["xOffset"] as number || 0); + let screenY = de.y - (de.data["yOffset"] as number || 0); + const [x, y] = this.getTransform().transformPoint(screenX, screenY); + doc.SetNumber(KeyStore.X, x); + doc.SetNumber(KeyStore.Y, y); + this.bringToFront(doc); + } } + @observable + _marquee = false; + @action onPointerDown = (e: React.PointerEvent): void => { - if ((e.button === 2 && this.props.active()) || - !e.defaultPrevented) { + if (((e.button === 2 && this.props.active()) || !e.defaultPrevented) && !e.shiftKey && + (!this.isAnnotationOverlay || this.zoomScaling != 1 || e.button == 0)) { document.removeEventListener("pointermove", this.onPointerMove); document.addEventListener("pointermove", this.onPointerMove); document.removeEventListener("pointerup", this.onPointerUp); @@ -84,7 +95,16 @@ export class CollectionFreeFormView extends CollectionViewBase { document.removeEventListener("pointermove", this.onPointerMove); document.removeEventListener("pointerup", this.onPointerUp); e.stopPropagation(); - if (Math.abs(this._downX - e.clientX) < 3 && Math.abs(this._downY - e.clientY) < 3) { + + if (this._marquee) { + if (!e.shiftKey) { + SelectionManager.DeselectAll(); + } + var selectedDocs = this.marqueeSelect(); + selectedDocs.map(s => this.props.CollectionView.SelectedDocs.push(s.Id)); + this._marquee = false; + } + else if (!this._marquee && Math.abs(this._downX - e.clientX) < 3 && Math.abs(this._downY - e.clientY) < 3) { //show preview text cursor on tap this._previewCursorVisible = true; //select is not already selected @@ -95,21 +115,73 @@ export class CollectionFreeFormView extends CollectionViewBase { } + intersectRect(r1: { left: number, right: number, top: number, bottom: number }, + r2: { left: number, right: number, top: number, bottom: number }) { + return !(r2.left > r1.right || + r2.right < r1.left || + r2.top > r1.bottom || + r2.bottom < r1.top); + } + + marqueeSelect() { + this.props.CollectionView.SelectedDocs.length = 0; + var curPage = this.props.Document.GetNumber(KeyStore.CurPage, 1); + let p = this.getTransform().transformPoint(this._downX, this._downY); + let v = this.getTransform().transformDirection(this._lastX - this._downX, this._lastY - this._downY); + let selRect = { left: p[0], top: p[1], right: p[0] + v[0], bottom: p[1] + v[1] } + + var curPage = this.props.Document.GetNumber(KeyStore.CurPage, 1); + const lvalue = this.props.Document.GetT<ListField<Document>>(this.props.fieldKey, ListField); + let selection: Document[] = []; + if (lvalue && lvalue != FieldWaiting) { + lvalue.Data.map(doc => { + var page = doc.GetNumber(KeyStore.Page, 0); + if (page == curPage || page == 0) { + var x = doc.GetNumber(KeyStore.X, 0); + var y = doc.GetNumber(KeyStore.Y, 0); + var w = doc.GetNumber(KeyStore.Width, 0); + var h = doc.GetNumber(KeyStore.Height, 0); + if (this.intersectRect({ left: x, top: y, right: x + w, bottom: y + h }, selRect)) + selection.push(doc) + } + }) + } + return selection; + } + @action onPointerMove = (e: PointerEvent): void => { if (!e.cancelBubble && this.props.active()) { e.stopPropagation(); - let x = this.props.Document.GetNumber(KeyStore.PanX, 0); - let y = this.props.Document.GetNumber(KeyStore.PanY, 0); - let [dx, dy] = this.getTransform().transformDirection(e.clientX - this._lastX, e.clientY - this._lastY); - this._previewCursorVisible = false; - this.SetPan(x - dx, y - dy); + e.preventDefault(); + let wasMarquee = this._marquee; + this._marquee = e.buttons != 2; + if (this._marquee && !wasMarquee) { + document.addEventListener("keydown", this.marqueeCommand); + } + + if (!this._marquee) { + let x = this.props.Document.GetNumber(KeyStore.PanX, 0); + let y = this.props.Document.GetNumber(KeyStore.PanY, 0); + let [dx, dy] = this.getTransform().transformDirection(e.clientX - this._lastX, e.clientY - this._lastY); + this._previewCursorVisible = false; + this.SetPan(x - dx, y - dy); + } } this._lastX = e.pageX; this._lastY = e.pageY; } @action + marqueeCommand = (e: KeyboardEvent) => { + if (e.key == "Backspace") { + this.marqueeSelect().map(d => this.props.removeDocument(d)); + } + if (e.key == "c") { + } + } + + @action onPointerWheel = (e: React.WheelEvent): void => { e.stopPropagation(); e.preventDefault(); @@ -136,7 +208,7 @@ export class CollectionFreeFormView extends CollectionViewBase { let localTransform = this.getLocalTransform() localTransform = localTransform.inverse().scaleAbout(deltaScale, x, y) - console.log(localTransform) + // console.log(localTransform) this.props.Document.SetNumber(KeyStore.Scale, localTransform.Scale); this.SetPan(-localTransform.TranslateX / localTransform.Scale, -localTransform.TranslateY / localTransform.Scale); @@ -145,8 +217,10 @@ export class CollectionFreeFormView extends CollectionViewBase { @action private SetPan(panX: number, panY: number) { - const newPanX = Math.max((1 - this.zoomScaling) * this.nativeWidth, Math.min(0, panX)); - const newPanY = Math.max((1 - this.zoomScaling) * this.nativeHeight, Math.min(0, panY)); + var x1 = this.getLocalTransform().inverse().Scale; + var x2 = this.getTransform().inverse().Scale; + const newPanX = Math.min((1 - 1 / x1) * this.nativeWidth, Math.max(0, panX)); + const newPanY = Math.min((1 - 1 / x1) * this.nativeHeight, Math.max(0, panY)); this.props.Document.SetNumber(KeyStore.PanX, this.isAnnotationOverlay ? newPanX : panX); this.props.Document.SetNumber(KeyStore.PanY, this.isAnnotationOverlay ? newPanY : panY); } @@ -219,21 +293,24 @@ export class CollectionFreeFormView extends CollectionViewBase { @computed get views() { + var curPage = this.props.Document.GetNumber(KeyStore.CurPage, 1); const lvalue = this.props.Document.GetT<ListField<Document>>(this.props.fieldKey, ListField); if (lvalue && lvalue != FieldWaiting) { return lvalue.Data.map(doc => { - return (<CollectionFreeFormDocumentView key={doc.Id} Document={doc} - AddDocument={this.props.addDocument} - RemoveDocument={this.props.removeDocument} - ScreenToLocalTransform={this.getTransform} - isTopMost={false} - SelectOnLoad={doc.Id === this._selectOnLoaded} - ContentScaling={this.noScaling} - PanelWidth={doc.Width} - PanelHeight={doc.Height} - ContainingCollectionView={this.props.CollectionView} - focus={this.focusDocument} - />); + var page = doc.GetNumber(KeyStore.Page, 0); + return (page != curPage && page != 0) ? (null) : + (<CollectionFreeFormDocumentView key={doc.Id} Document={doc} + AddDocument={this.props.addDocument} + RemoveDocument={this.props.removeDocument} + ScreenToLocalTransform={this.getTransform} + isTopMost={false} + SelectOnLoad={doc.Id === this._selectOnLoaded} + ContentScaling={this.noScaling} + PanelWidth={doc.Width} + PanelHeight={doc.Height} + ContainingCollectionView={this.props.CollectionView} + focus={this.focusDocument} + />); }) } return null; @@ -243,7 +320,7 @@ export class CollectionFreeFormView extends CollectionViewBase { get backgroundView() { return !this.backgroundLayout ? (null) : (<JsxParser - components={{ FormattedTextBox, ImageBox, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView, WebBox, KeyValueBox }} + components={{ FormattedTextBox, ImageBox, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView, CollectionPDFView, WebBox, KeyValueBox, PDFBox }} bindings={this.props.bindings} jsx={this.backgroundLayout} showWarnings={true} @@ -254,7 +331,7 @@ export class CollectionFreeFormView extends CollectionViewBase { get overlayView() { return !this.overlayLayout ? (null) : (<JsxParser - components={{ FormattedTextBox, ImageBox, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView, WebBox, KeyValueBox }} + components={{ FormattedTextBox, ImageBox, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView, CollectionPDFView, WebBox, KeyValueBox, PDFBox }} bindings={this.props.bindings} jsx={this.overlayLayout} showWarnings={true} @@ -273,7 +350,6 @@ export class CollectionFreeFormView extends CollectionViewBase { } render() { - //determines whether preview text cursor should be visible (ie when user taps this collection it should) let cursor = null; if (this._previewCursorVisible) { @@ -282,13 +358,17 @@ export class CollectionFreeFormView extends CollectionViewBase { cursor = <div id="prevCursor" onKeyPress={this.onKeyDown} style={{ color: "black", position: "absolute", transformOrigin: "left top", transform: `translate(${x}px, ${y}px)` }}>I</div> } + let p = this.getTransform().transformPoint(this._downX < this._lastX ? this._downX : this._lastX, this._downY < this._lastY ? this._downY : this._lastY); + let v = this.getTransform().transformDirection(this._lastX - this._downX, this._lastY - this._downY); + var marquee = this._marquee ? <div className="collectionfreeformview-marquee" style={{ transform: `translate(${p[0]}px, ${p[1]}px)`, width: `${Math.abs(v[0])}`, height: `${Math.abs(v[1])}` }}></div> : (null); + let [dx, dy] = [this.centeringShiftX, this.centeringShiftY]; const panx: number = -this.props.Document.GetNumber(KeyStore.PanX, 0); const pany: number = -this.props.Document.GetNumber(KeyStore.PanY, 0); return ( - <div className="collectionfreeformview-container" + <div className={`collectionfreeformview${this.isAnnotationOverlay ? "-overlay" : "-container"}`} onPointerDown={this.onPointerDown} onKeyPress={this.onKeyDown} onWheel={this.onPointerWheel} @@ -302,11 +382,13 @@ export class CollectionFreeFormView extends CollectionViewBase { style={{ transformOrigin: "left top", transform: `translate(${dx}px, ${dy}px) scale(${this.zoomScaling}, ${this.zoomScaling}) translate(${panx}px, ${pany}px)` }} ref={this._canvasRef}> {this.backgroundView} + <InkingCanvas getScreenTransform={this.getTransform} Document={this.props.Document} /> {cursor} {this.views} + {marquee} </div> {this.overlayView} </div> ); } -}
\ No newline at end of file +} diff --git a/src/client/views/collections/CollectionPDFView.tsx b/src/client/views/collections/CollectionPDFView.tsx new file mode 100644 index 000000000..f22c07060 --- /dev/null +++ b/src/client/views/collections/CollectionPDFView.tsx @@ -0,0 +1,57 @@ +import { action, computed } from "mobx"; +import { observer } from "mobx-react"; +import { Document } from "../../../fields/Document"; +import { KeyStore } from "../../../fields/KeyStore"; +import { ContextMenu } from "../ContextMenu"; +import { CollectionView, CollectionViewType } from "./CollectionView"; +import { CollectionViewProps } from "./CollectionViewBase"; +import React = require("react"); +import { FieldId } from "../../../fields/Field"; + + +@observer +export class CollectionPDFView extends React.Component<CollectionViewProps> { + + public static LayoutString(fieldKey: string = "DataKey") { + return `<${CollectionPDFView.name} Document={Document} + ScreenToLocalTransform={ScreenToLocalTransform} fieldKey={${fieldKey}} panelWidth={PanelWidth} panelHeight={PanelHeight} isSelected={isSelected} select={select} bindings={bindings} + isTopMost={isTopMost} SelectOnLoad={selectOnLoad} BackgroundView={BackgroundView} focus={focus}/>`; + } + + public SelectedDocs: FieldId[] = [] + @action onPageBack = () => this.curPage > 1 ? this.props.Document.SetNumber(KeyStore.CurPage, this.curPage - 1) : 0; + @action onPageForward = () => this.curPage < this.numPages ? this.props.Document.SetNumber(KeyStore.CurPage, this.curPage + 1) : 0; + + @computed private get curPage() { return this.props.Document.GetNumber(KeyStore.CurPage, 0); } + @computed private get numPages() { return this.props.Document.GetNumber(KeyStore.NumPages, 0); } + @computed private get uIButtons() { + return ( + <div className="pdfBox-buttonTray" key="tray"> + <button className="pdfButton" onClick={this.onPageBack}>{"<"}</button> + <button className="pdfButton" onClick={this.onPageForward}>{">"}</button> + </div>); + } + + // "inherited" CollectionView API starts here... + + public active: () => boolean = () => CollectionView.Active(this); + + addDocument = (doc: Document): void => { CollectionView.AddDocument(this.props, doc); } + removeDocument = (doc: Document): boolean => { return CollectionView.RemoveDocument(this.props, doc); } + + specificContextMenu = (e: React.MouseEvent): void => { + if (!e.isPropagationStopped() && this.props.Document.Id != "mainDoc") { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7 + ContextMenu.Instance.addItem({ description: "PDFOptions", event: () => { } }); + } + } + + get collectionViewType(): CollectionViewType { return CollectionViewType.Freeform; } + get subView(): any { return CollectionView.SubView(this); } + + render() { + return (<div className="collectionView-cont" onContextMenu={this.specificContextMenu}> + {this.subView} + {this.props.isSelected() ? this.uIButtons : (null)} + </div>) + } +}
\ No newline at end of file diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index 49f95c014..04f017378 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -203,6 +203,8 @@ export class CollectionSchemaView extends CollectionViewBase { ) let previewHandle = !this.props.active() ? (null) : ( <div className="collectionSchemaView-previewHandle" onPointerDown={this.onExpanderDown} />); + let dividerDragger = this._splitPercentage == 100 ? (null) : + <div className="collectionSchemaView-dividerDragger" onPointerDown={this.onDividerDown} style={{ width: `${this.DIVIDER_WIDTH}px` }} /> return ( <div className="collectionSchemaView-container" onPointerDown={this.onPointerDown} ref={this._mainCont} style={{ borderWidth: `${COLLECTION_BORDER_WIDTH}px` }} > <div className="collectionSchemaView-dropTarget" onDrop={(e: React.DragEvent) => this.onDrop(e, {})} ref={this.createDropTarget}> @@ -232,7 +234,7 @@ export class CollectionSchemaView extends CollectionViewBase { </div> } </Measure> - <div className="collectionSchemaView-dividerDragger" onPointerDown={this.onDividerDown} style={{ width: `${this.DIVIDER_WIDTH}px` }} /> + {dividerDragger} <div className="collectionSchemaView-previewRegion" style={{ width: `calc(${100 - this._splitPercentage}% - ${this.DIVIDER_WIDTH}px)` }}> {content} </div> diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 31824763d..548a51bf1 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -1,4 +1,4 @@ -import { action } from "mobx"; +import { action, computed, observable } from "mobx"; import { observer } from "mobx-react"; import { Document } from "../../../fields/Document"; import { ListField } from "../../../fields/ListField"; @@ -12,7 +12,7 @@ import { CollectionDockingView } from "./CollectionDockingView"; import { CollectionSchemaView } from "./CollectionSchemaView"; import { CollectionViewProps } from "./CollectionViewBase"; import { CollectionTreeView } from "./CollectionTreeView"; -import { Field } from "../../../fields/Field"; +import { Field, FieldId } from "../../../fields/Field"; export enum CollectionViewType { Invalid, @@ -27,33 +27,43 @@ export const COLLECTION_BORDER_WIDTH = 2; @observer export class CollectionView extends React.Component<CollectionViewProps> { + @observable + public SelectedDocs: FieldId[] = []; + public static LayoutString(fieldKey: string = "DataKey") { - return `<CollectionView Document={Document} + return `<${CollectionView.name} Document={Document} ScreenToLocalTransform={ScreenToLocalTransform} fieldKey={${fieldKey}} panelWidth={PanelWidth} panelHeight={PanelHeight} isSelected={isSelected} select={select} bindings={bindings} isTopMost={isTopMost} SelectOnLoad={selectOnLoad} BackgroundView={BackgroundView} focus={focus}/>`; } - public active = () => { - var isSelected = this.props.isSelected(); - var childSelected = SelectionManager.SelectedDocuments().some(view => view.props.ContainingCollectionView == this); - var topMost = this.props.isTopMost; + + public active: () => boolean = () => CollectionView.Active(this); + addDocument = (doc: Document): void => { CollectionView.AddDocument(this.props, doc); } + removeDocument = (doc: Document): boolean => { return CollectionView.RemoveDocument(this.props, doc); } + get subView() { return CollectionView.SubView(this); } + + public static Active(self: CollectionView): boolean { + var isSelected = self.props.isSelected(); + var childSelected = SelectionManager.SelectedDocuments().some(view => view.props.ContainingCollectionView == self); + var topMost = self.props.isTopMost; return isSelected || childSelected || topMost; } + @action - addDocument = (doc: Document): void => { - if (this.props.Document.Get(this.props.fieldKey) instanceof Field) { + public static AddDocument(props: CollectionViewProps, doc: Document) { + doc.SetNumber(KeyStore.Page, props.Document.GetNumber(KeyStore.CurPage, 0)); + if (props.Document.Get(props.fieldKey) instanceof Field) { //TODO This won't create the field if it doesn't already exist - const value = this.props.Document.GetData(this.props.fieldKey, ListField, new Array<Document>()) + const value = props.Document.GetData(props.fieldKey, ListField, new Array<Document>()) value.push(doc); } else { - this.props.Document.SetData(this.props.fieldKey, [doc], ListField); + props.Document.SetData(props.fieldKey, [doc], ListField); } } - @action - removeDocument = (doc: Document): boolean => { + public static RemoveDocument(props: CollectionViewProps, doc: Document): boolean { //TODO This won't create the field if it doesn't already exist - const value = this.props.Document.GetData(this.props.fieldKey, ListField, new Array<Document>()) + const value = props.Document.GetData(props.fieldKey, ListField, new Array<Document>()) let index = -1; for (let i = 0; i < value.length; i++) { if (value[i].Id == doc.Id) { @@ -84,13 +94,8 @@ export class CollectionView extends React.Component<CollectionViewProps> { } } - set collectionViewType(type: CollectionViewType) { - let Document = this.props.Document; - Document.SetData(KeyStore.ViewType, type, NumberField); - } - specificContextMenu = (e: React.MouseEvent): void => { - if (!e.isPropagationStopped) { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7 + if (!e.isPropagationStopped() && this.props.Document.Id != "mainDoc") { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7 ContextMenu.Instance.addItem({ description: "Freeform", event: () => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Freeform) }) ContextMenu.Instance.addItem({ description: "Schema", event: () => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Schema) }) ContextMenu.Instance.addItem({ description: "Treeview", event: () => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Tree) }) @@ -98,36 +103,20 @@ export class CollectionView extends React.Component<CollectionViewProps> { } } - render() { - let viewType = this.collectionViewType; - let subView: JSX.Element; - switch (viewType) { - case CollectionViewType.Freeform: - subView = (<CollectionFreeFormView {...this.props} - addDocument={this.addDocument} removeDocument={this.removeDocument} active={this.active} - CollectionView={this} />) - break; - case CollectionViewType.Schema: - subView = (<CollectionSchemaView {...this.props} - addDocument={this.addDocument} removeDocument={this.removeDocument} active={this.active} - CollectionView={this} />) - break; - case CollectionViewType.Docking: - subView = (<CollectionDockingView {...this.props} - addDocument={this.addDocument} removeDocument={this.removeDocument} active={this.active} - CollectionView={this} />) - break; - case CollectionViewType.Tree: - subView = (<CollectionTreeView {...this.props} - addDocument={this.addDocument} removeDocument={this.removeDocument} active={this.active} - CollectionView={this} />) - break; - default: - subView = <div></div> - break; + public static SubView(self: CollectionView) { + let subProps = { ...self.props, addDocument: self.addDocument, removeDocument: self.removeDocument, active: self.active, CollectionView: self } + switch (self.collectionViewType) { + case CollectionViewType.Freeform: return (<CollectionFreeFormView {...subProps} />) + case CollectionViewType.Schema: return (<CollectionSchemaView {...subProps} />) + case CollectionViewType.Docking: return (<CollectionDockingView {...subProps} />) + case CollectionViewType.Tree: return (<CollectionTreeView {...subProps} />) } - return (<div onContextMenu={this.specificContextMenu}> - {subView} + return (null); + } + + render() { + return (<div className="collectionView-cont" onContextMenu={this.specificContextMenu}> + {this.subView} </div>) } -}
\ No newline at end of file +} diff --git a/src/client/views/collections/CollectionViewBase.tsx b/src/client/views/collections/CollectionViewBase.tsx index 0a3b965f2..b126b40a9 100644 --- a/src/client/views/collections/CollectionViewBase.tsx +++ b/src/client/views/collections/CollectionViewBase.tsx @@ -1,4 +1,4 @@ -import { action } from "mobx"; +import { action, runInAction } from "mobx"; import { Document } from "../../../fields/Document"; import { ListField } from "../../../fields/ListField"; import React = require("react"); @@ -47,7 +47,7 @@ export class CollectionViewBase extends React.Component<SubCollectionViewProps> protected drop(e: Event, de: DragManager.DropEvent) { const docView: DocumentView = de.data["documentView"]; const doc: Document = de.data["document"]; - if (docView && docView.props.ContainingCollectionView && docView.props.ContainingCollectionView !== this.props.CollectionView) { + if (docView && (!docView.props.ContainingCollectionView || docView.props.ContainingCollectionView !== this.props.CollectionView)) { if (docView.props.RemoveDocument) { docView.props.RemoveDocument(docView.props.Document); } @@ -68,13 +68,17 @@ export class CollectionViewBase extends React.Component<SubCollectionViewProps> let html = e.dataTransfer.getData("text/html"); let text = e.dataTransfer.getData("text/plain"); if (html && html.indexOf("<img") != 0) { + console.log("not good"); let htmlDoc = Documents.HtmlDocument(html, { ...options, width: 300, height: 300 }); htmlDoc.SetText(KeyStore.DocumentText, text); this.props.addDocument(htmlDoc); return; } + console.log(e.dataTransfer.items.length); + for (let i = 0; i < e.dataTransfer.items.length; i++) { + const upload = window.location.origin + "/upload"; let item = e.dataTransfer.items[i]; if (item.kind === "string" && item.type.indexOf("uri") != -1) { e.dataTransfer.items[i].getAsString(function (s) { @@ -93,28 +97,55 @@ export class CollectionViewBase extends React.Component<SubCollectionViewProps> }) } - if (item.kind == "file" && item.type.indexOf("image")) { + let type = item.type + console.log(type) + if (item.kind == "file") { let fReader = new FileReader() let file = item.getAsFile(); - - fReader.addEventListener("load", action("drop", () => { - if (fReader.result) { - let url = "" + fReader.result; - let doc = Documents.ImageDocument(url, options) - let docs = that.props.Document.GetT(KeyStore.Data, ListField); - if (docs != FieldWaiting) { - if (!docs) { - docs = new ListField<Document>(); - that.props.Document.Set(KeyStore.Data, docs) - } - docs.Data.push(doc); - } - } - }), false) + let formData = new FormData() if (file) { - fReader.readAsDataURL(file) + formData.append('file', file) } + + fetch(upload, { + method: 'POST', + body: formData + }) + .then((res: Response) => { + return res.json() + }).then(json => { + + json.map((file: any) => { + let path = window.location.origin + file + runInAction(() => { + var doc: any; + + if (type.indexOf("image") !== -1) { + doc = Documents.ImageDocument(path, { ...options, nativeWidth: 300, width: 300, }) + } + if (type.indexOf("video") !== -1) { + doc = Documents.VideoDocument(path, { ...options, nativeWidth: 300, width: 300, }) + } + if (type.indexOf("audio") !== -1) { + doc = Documents.AudioDocument(path, { ...options, nativeWidth: 300, width: 300, }) + } + let docs = that.props.Document.GetT(KeyStore.Data, ListField); + if (docs != FieldWaiting) { + if (!docs) { + docs = new ListField<Document>(); + that.props.Document.Set(KeyStore.Data, docs) + } + if (doc) { + docs.Data.push(doc); + } + + } + }) + }) + }) + + } } } |
