From 6df3143ead642356b7823946e9710f840f3faa5a Mon Sep 17 00:00:00 2001 From: _stanleyyip <33562077+yipstanley@users.noreply.github.com> Date: Tue, 14 May 2019 16:02:37 -0400 Subject: argh --- src/client/views/nodes/DocumentContentsView.tsx | 1 + 1 file changed, 1 insertion(+) (limited to 'src/client/views/nodes/DocumentContentsView.tsx') diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx index f404b7bc6..11df9162a 100644 --- a/src/client/views/nodes/DocumentContentsView.tsx +++ b/src/client/views/nodes/DocumentContentsView.tsx @@ -23,6 +23,7 @@ import { FieldViewProps } from "./FieldView"; import { Without, OmitKeys } from "../../../Utils"; import { Cast, StrCast } from "../../../new_fields/Types"; import { List } from "../../../new_fields/List"; +import { PDFBox2 } from "../pdf/PDFBox2"; const JsxParser = require('react-jsx-parser').default; //TODO Why does this need to be imported like this? type BindingProps = Without; -- cgit v1.2.3-70-g09d2 From 464fa03d6ebb2a7aaef1d7622afa3e1e7ee816a3 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Tue, 18 Jun 2019 20:11:31 -0400 Subject: Context menu improvements and error fixes --- src/client/views/ContextMenu.scss | 22 +++++----- src/client/views/ContextMenuItem.tsx | 47 +++++++++++++++++++--- .../views/collections/CollectionSchemaView.tsx | 1 + src/client/views/nodes/DocumentContentsView.tsx | 1 - src/client/views/nodes/DocumentView.tsx | 5 ++- 5 files changed, 57 insertions(+), 19 deletions(-) (limited to 'src/client/views/nodes/DocumentContentsView.tsx') diff --git a/src/client/views/ContextMenu.scss b/src/client/views/ContextMenu.scss index 7e066d53a..e363c5158 100644 --- a/src/client/views/ContextMenu.scss +++ b/src/client/views/ContextMenu.scss @@ -8,19 +8,19 @@ flex-direction: column; } -.contextMenu-item:first-child { - background: $intermediate-color; - color: $light-color; -} +// .contextMenu-item:first-child { +// background: $intermediate-color; +// color: $light-color; +// } -.contextMenu-item:first-child::placeholder { - color: $light-color; -} +// .contextMenu-item:first-child::placeholder { +// color: $light-color; +// } -.contextMenu-item:first-child:hover { - background: $intermediate-color; - color: $light-color; -} +// .contextMenu-item:first-child:hover { +// background: $intermediate-color; +// color: $light-color; +// } .contextMenu-subMenu-cont { position: absolute; diff --git a/src/client/views/ContextMenuItem.tsx b/src/client/views/ContextMenuItem.tsx index fcda0db89..dc0751049 100644 --- a/src/client/views/ContextMenuItem.tsx +++ b/src/client/views/ContextMenuItem.tsx @@ -1,9 +1,12 @@ import React = require("react"); import { observable, action } from "mobx"; import { observer } from "mobx-react"; -import { IconProp } from '@fortawesome/fontawesome-svg-core'; +import { IconProp, library } from '@fortawesome/fontawesome-svg-core'; +import { faAngleRight } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +library.add(faAngleRight); + export interface OriginalMenuProps { description: string; event: (e: React.MouseEvent) => void; @@ -14,6 +17,7 @@ export interface OriginalMenuProps { export interface SubmenuProps { description: string; subitems: ContextMenuProps[]; + icon?: IconProp; //maybe should be optional (icon?) closeMenu?: () => void; } @@ -41,13 +45,40 @@ export class ContextMenuItem extends React.Component { } } + currentTimeout?: any; + static readonly timeout = 300; + onPointerEnter = () => { + if (this.currentTimeout) { + clearTimeout(this.currentTimeout); + this.currentTimeout = undefined; + } + if (this.overItem) { + return; + } + this.currentTimeout = setTimeout(action(() => this.overItem = true), ContextMenuItem.timeout); + } + + onPointerLeave = () => { + if (this.currentTimeout) { + clearTimeout(this.currentTimeout); + this.currentTimeout = undefined; + } + if (!this.overItem) { + return; + } + this.currentTimeout = setTimeout(action(() => this.overItem = false), ContextMenuItem.timeout); + + } + render() { if ("event" in this.props) { return (
- - {this.props.icon ? : } - + {this.props.icon ? ( + + + + ) : null}
{this.props.description}
@@ -60,9 +91,15 @@ export class ContextMenuItem extends React.Component { {this._items.map(prop => )}
; return ( -
{ this.overItem = true; })} onMouseLeave={action(() => this.overItem = false)}> +
+ {this.props.icon ? ( + + + + ) : null}
{this.props.description} +
{submenu}
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index 4b46c73c1..14a7d19d0 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -352,6 +352,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { height={this.previewHeight} getTransform={this.getPreviewTransform} CollectionView={this.props.CollectionView} + moveDocument={this.props.moveDocument} addDocument={this.props.addDocument} removeDocument={this.props.removeDocument} active={this.props.active} diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx index c2caabb92..02396c3af 100644 --- a/src/client/views/nodes/DocumentContentsView.tsx +++ b/src/client/views/nodes/DocumentContentsView.tsx @@ -23,7 +23,6 @@ import { FieldViewProps } from "./FieldView"; import { Without, OmitKeys } from "../../../Utils"; import { Cast, StrCast, NumCast } from "../../../new_fields/Types"; import { List } from "../../../new_fields/List"; -import { PDFBox2 } from "../pdf/PDFBox2"; const JsxParser = require('react-jsx-parser').default; //TODO Why does this need to be imported like this? type BindingProps = Without; diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index de6e9f5fa..7c058d91c 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -1,5 +1,5 @@ import { library } from '@fortawesome/fontawesome-svg-core'; -import { faAlignCenter, faCaretSquareRight, faCompressArrowsAlt, faUnlock, faLock, faExpandArrowsAlt, faLayerGroup, faSquare, faTrash, faConciergeBell, faFolder, faMapPin, faLink, faFingerprint, faCrosshairs, faDesktop } from '@fortawesome/free-solid-svg-icons'; +import { faAlignCenter, faCaretSquareRight, faCompressArrowsAlt, faUnlock, faLock, faExpandArrowsAlt, faLayerGroup, faSquare, faTrash, faConciergeBell, faFolder, faShare, faMapPin, faLink, faFingerprint, faCrosshairs, faDesktop } from '@fortawesome/free-solid-svg-icons'; import { action, computed, IReactionDisposer, reaction, trace, observable, runInAction } from "mobx"; import { observer } from "mobx-react"; import { Doc, DocListCast, HeightSym, Opt, WidthSym, DocListCastAsync } from "../../../new_fields/Doc"; @@ -35,6 +35,7 @@ import { RouteStore } from '../../../server/RouteStore'; const JsxParser = require('react-jsx-parser').default; //TODO Why does this need to be imported like this? library.add(faTrash); +library.add(faShare); library.add(faExpandArrowsAlt); library.add(faCompressArrowsAlt); library.add(faLayerGroup); @@ -510,7 +511,7 @@ export class DocumentView extends DocComponent(Docu } })); runInAction(() => { - cm.addItem({ description: "Share...", subitems: usersMenu }); + cm.addItem({ description: "Share...", subitems: usersMenu, icon: "share" }); if (!this.topMost) { // DocumentViews should stop propagation of this event e.stopPropagation(); -- cgit v1.2.3-70-g09d2 From e495d4e32402384dbf7bb72945e83c912fce892b Mon Sep 17 00:00:00 2001 From: bob Date: Thu, 20 Jun 2019 17:46:56 -0400 Subject: first shot at templates... --- src/client/views/MainOverlayTextBox.tsx | 6 ++-- src/client/views/MainView.tsx | 1 + .../views/collections/CollectionDockingView.tsx | 4 ++- .../views/collections/CollectionSchemaView.tsx | 3 +- .../views/collections/CollectionStackingView.tsx | 4 ++- src/client/views/collections/CollectionView.tsx | 37 ++++++++++++++++++++++ .../collectionFreeForm/CollectionFreeFormView.tsx | 1 + src/client/views/nodes/DocumentContentsView.tsx | 12 ++++--- src/client/views/nodes/DocumentView.tsx | 1 + src/client/views/nodes/FieldView.tsx | 1 + src/client/views/nodes/FormattedTextBox.tsx | 32 ++++++++++--------- 11 files changed, 77 insertions(+), 25 deletions(-) (limited to 'src/client/views/nodes/DocumentContentsView.tsx') diff --git a/src/client/views/MainOverlayTextBox.tsx b/src/client/views/MainOverlayTextBox.tsx index b4ad5f4d7..64271650b 100644 --- a/src/client/views/MainOverlayTextBox.tsx +++ b/src/client/views/MainOverlayTextBox.tsx @@ -37,7 +37,7 @@ export class MainOverlayTextBox extends React.Component (box?: FormattedTextBox) => { this._textBox = box; if (box) { - this.TextDoc = box.props.Document; + this.TextDoc = box.props.DataDoc; let sxf = Utils.GetScreenTransform(box ? box.CurrentDiv : undefined); let xf = () => { box.props.ScreenToLocalTransform(); return new Transform(-sxf.translateX, -sxf.translateY, 1 / sxf.scale); }; this.setTextDoc(box.props.fieldKey, box.CurrentDiv, xf, BoolCast(box.props.Document.autoHeight, false) || box.props.height === "min-content"); @@ -118,7 +118,9 @@ export class MainOverlayTextBox extends React.Component
- diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 51630c29b..8198b88d2 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -203,6 +203,7 @@ export class MainView extends React.Component { let mainCont = this.mainContainer; let content = !mainCont ? (null) : { return (
- doc) { renderCell = (rowProps: CellInfo) => { let props: FieldViewProps = { Document: rowProps.original, + DataDoc: rowProps.original, fieldKey: rowProps.column.id as string, ContainingCollectionView: this.props.CollectionView, isSelected: returnFalse, @@ -423,7 +424,7 @@ export class CollectionSchemaPreview extends React.Component {!this.props.Document || !this.props.width ? (null) : (
- doc) { gridColumnEnd: `span 1`, transform: `scale(${renderScale})` }} > - { subItems.push({ description: "Treeview", event: undoBatch(() => this.props.Document.viewType = CollectionViewType.Tree), icon: "tree" }); subItems.push({ description: "Stacking", event: undoBatch(() => this.props.Document.viewType = CollectionViewType.Stacking), icon: "th-list" }); ContextMenu.Instance.addItem({ description: "View Modes...", subitems: subItems }); + ContextMenu.Instance.addItem({ + description: "Add Description Template", event: undoBatch(() => { + Doc.GetProto(this.props.Document).description = "my first templated box"; + let template = Doc.MakeAlias(this.props.Document); + template.layout = FormattedTextBox.LayoutString("description"); + template.x = 0; + template.y = 0; + template.width = 100; + template.height = 25; + Doc.AddDocToList(this.props.Document, "data", template); + }), icon: "project-diagram" + }); + ContextMenu.Instance.addItem({ + description: "Add Summary Template", event: undoBatch(() => { + Doc.GetProto(this.props.Document).summary = "my first templated box"; + let template = Doc.MakeAlias(this.props.Document); + template.layout = FormattedTextBox.LayoutString("summary"); + template.x = 0; + template.y = 0; + template.width = 100; + template.height = 25; + Doc.AddDocToList(this.props.Document, "data", template); + }), icon: "project-diagram" + }); + ContextMenu.Instance.addItem({ + description: "Apply Template", event: undoBatch(() => { + let otherdoc = Docs.TextDocument({ width: 100, height: 50, title: "applied template" }); + Doc.GetProto(otherdoc).description = "THIS DESCRIPTION IS REALLY IMPORTANT!"; + Doc.GetProto(otherdoc).summary = "THIS SUMMARY IS MEANINGFUL!"; + Doc.GetProto(otherdoc).layout = this.props.Document; + this.props.addDocTab && this.props.addDocTab(otherdoc, "onRight"); + }), icon: "project-diagram" + }); } } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 84841e469..013c11837 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -296,6 +296,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { getDocumentViewProps(document: Doc): DocumentViewProps { return { Document: document, + DataDoc: this.props.DataDoc, addDocument: this.props.addDocument, removeDocument: this.props.removeDocument, moveDocument: this.props.moveDocument, diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx index 02396c3af..a4316c143 100644 --- a/src/client/views/nodes/DocumentContentsView.tsx +++ b/src/client/views/nodes/DocumentContentsView.tsx @@ -23,6 +23,7 @@ import { FieldViewProps } from "./FieldView"; import { Without, OmitKeys } from "../../../Utils"; import { Cast, StrCast, NumCast } from "../../../new_fields/Types"; import { List } from "../../../new_fields/List"; +import { Doc } from "../../../new_fields/Doc"; const JsxParser = require('react-jsx-parser').default; //TODO Why does this need to be imported like this? type BindingProps = Without; @@ -47,11 +48,12 @@ export class DocumentContentsView extends React.Component { @computed get layout(): string { - const layout = Cast(this.props.Document[this.props.layoutKey], "string"); + let layoutDoc = this.props.Document.layout instanceof Doc ? this.props.Document.layout : this.props.Document; + const layout = Cast(layoutDoc[this.props.layoutKey], "string"); if (layout === undefined) { return this.props.Document.data ? "" : - KeyValueBox.LayoutString(this.props.Document.proto ? "proto" : ""); + KeyValueBox.LayoutString(layoutDoc.proto ? "proto" : ""); } else if (typeof layout === "string") { return layout; } else { @@ -59,8 +61,8 @@ export class DocumentContentsView extends React.Component obj.active = this.props.parentActive).omit }; + CreateBindings(layoutDoc?: Doc): JsxBindings { + return { props: { ...OmitKeys(this.props, ['parentActive'], (obj: any) => obj.active = this.props.parentActive).omit, Document: layoutDoc } }; } @computed get templates(): List { @@ -104,7 +106,7 @@ export class DocumentContentsView extends React.Component { console.log(test); }} diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 280804630..93b883533 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -67,6 +67,7 @@ const LinkDoc = makeInterface(linkSchema); export interface DocumentViewProps { ContainingCollectionView: Opt; Document: Doc; + DataDoc: Doc; addDocument?: (doc: Doc, allowDuplicates?: boolean) => boolean; removeDocument?: (doc: Doc) => boolean; moveDocument?: (doc: Doc, targetCollection: Doc, addDocument: (document: Doc) => boolean) => boolean; diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx index 1f1582f22..35608af86 100644 --- a/src/client/views/nodes/FieldView.tsx +++ b/src/client/views/nodes/FieldView.tsx @@ -30,6 +30,7 @@ export interface FieldViewProps { fieldKey: string; ContainingCollectionView: Opt; Document: Doc; + DataDoc: Doc; isSelected: () => boolean; select: (isCtrlPressed: boolean) => void; isTopMost: boolean; diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index 376b5a574..8231cc089 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -1,6 +1,6 @@ import { library } from '@fortawesome/fontawesome-svg-core'; import { faEdit, faSmile } from '@fortawesome/free-solid-svg-icons'; -import { action, IReactionDisposer, observable, reaction, runInAction } from "mobx"; +import { action, IReactionDisposer, observable, reaction, runInAction, computed } from "mobx"; import { observer } from "mobx-react"; import { baseKeymap } from "prosemirror-commands"; import { history } from "prosemirror-history"; @@ -104,19 +104,21 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe } } + @computed get dataDoc() { return this.props.DataDoc; } + dispatchTransaction = (tx: Transaction) => { if (this._editorView) { const state = this._editorView.state.apply(tx); this._editorView.updateState(state); this._applyingChange = true; - Doc.SetOnPrototype(this.props.Document, this.props.fieldKey, new RichTextField(JSON.stringify(state.toJSON()))); - Doc.SetOnPrototype(this.props.Document, "documentText", state.doc.textBetween(0, state.doc.content.size, "\n\n")); + Doc.SetOnPrototype(this.dataDoc, this.props.fieldKey, new RichTextField(JSON.stringify(state.toJSON()))); + Doc.SetOnPrototype(this.dataDoc, "documentText", state.doc.textBetween(0, state.doc.content.size, "\n\n")); this._applyingChange = false; - let title = StrCast(this.props.Document.title); + let title = StrCast(this.dataDoc.title); if (title && title.startsWith("-") && this._editorView) { let str = this._editorView.state.doc.textContent; let titlestr = str.substr(0, Math.min(40, str.length)); - let target = this.props.Document.proto ? this.props.Document.proto : this.props.Document; + let target = this.dataDoc.proto ? this.dataDoc.proto : this.dataDoc; target.title = "-" + titlestr + (str.length > 40 ? "..." : ""); } } @@ -144,14 +146,14 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe e.stopPropagation(); } else { if (de.data instanceof DragManager.DocumentDragData) { - let ldocs = Cast(this.props.Document.subBulletDocs, listSpec(Doc)); + let ldocs = Cast(this.dataDoc.subBulletDocs, listSpec(Doc)); if (!ldocs) { - this.props.Document.subBulletDocs = new List([]); + this.dataDoc.subBulletDocs = new List([]); } - ldocs = Cast(this.props.Document.subBulletDocs, listSpec(Doc)); + ldocs = Cast(this.dataDoc.subBulletDocs, listSpec(Doc)); if (!ldocs) return; if (!ldocs || !ldocs[0] || ldocs[0] instanceof Promise || StrCast((ldocs[0] as Doc).layout).indexOf("CollectionView") === -1) { - ldocs.splice(0, 0, Docs.StackingDocument([], { title: StrCast(this.props.Document.title) + "-subBullets", x: NumCast(this.props.Document.x), y: NumCast(this.props.Document.y) + NumCast(this.props.Document.height), width: 300, height: 300 })); + ldocs.splice(0, 0, Docs.StackingDocument([], { title: StrCast(this.dataDoc.title) + "-subBullets", x: NumCast(this.props.Document.x), y: NumCast(this.props.Document.y) + NumCast(this.props.Document.height), width: 300, height: 300 })); this.props.addDocument && this.props.addDocument(ldocs[0] as Doc); this.props.Document.templates = new List([Templates.Bullet.Layout]); this.props.Document.isBullet = true; @@ -201,13 +203,13 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe this._reactionDisposer = reaction( () => { - const field = this.props.Document ? Cast(this.props.Document[this.props.fieldKey], RichTextField) : undefined; + const field = this.dataDoc ? Cast(this.dataDoc[this.props.fieldKey], RichTextField) : undefined; return field ? field.Data : `{"doc":{"type":"doc","content":[]},"selection":{"type":"text","anchor":0,"head":0}}`; }, field => this._editorView && !this._applyingChange && this._editorView.updateState(EditorState.fromJSON(config, JSON.parse(field))) ); - this.setupEditor(config, this.props.Document, this.props.fieldKey); + this.setupEditor(config, this.dataDoc, this.props.fieldKey); } private setupEditor(config: any, doc: Doc, fieldKey: string) { @@ -360,10 +362,10 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe // stop propagation doesn't seem to stop propagation of native keyboard events. // so we set a flag on the native event that marks that the event's been handled. (e.nativeEvent as any).DASHFormattedTextBoxHandled = true; - if (StrCast(this.props.Document.title).startsWith("-") && this._editorView) { + if (StrCast(this.dataDoc.title).startsWith("-") && this._editorView) { let str = this._editorView.state.doc.textContent; let titlestr = str.substr(0, Math.min(40, str.length)); - let target = this.props.Document.proto ? this.props.Document.proto : this.props.Document; + let target = this.dataDoc.proto ? this.dataDoc.proto : this.dataDoc; target.title = "-" + titlestr + (str.length > 40 ? "..." : ""); } if (!this._undoTyping) { @@ -372,11 +374,11 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe if (this.props.isOverlay && this.props.Document.autoHeight) { let xf = this._ref.current!.getBoundingClientRect(); let scrBounds = this.props.ScreenToLocalTransform().transformBounds(0, 0, xf.width, xf.height); - let nh = NumCast(this.props.Document.nativeHeight, 0); + let nh = NumCast(this.dataDoc.nativeHeight, 0); let dh = NumCast(this.props.Document.height, 0); let sh = scrBounds.height; this.props.Document.height = nh ? dh / nh * sh : sh; - this.props.Document.proto!.nativeHeight = nh ? sh : undefined; + this.dataDoc.proto!.nativeHeight = nh ? sh : undefined; } } -- cgit v1.2.3-70-g09d2 From 45ded4da2592bc2a8201e1260dfb6a80485684c7 Mon Sep 17 00:00:00 2001 From: bob Date: Tue, 25 Jun 2019 09:35:09 -0400 Subject: converted isTopMost into renderDepth and capped renderDepth at 7. removed previous cycle detection. --- src/client/documents/Documents.ts | 6 +-- src/client/util/DragManager.ts | 2 - src/client/views/DocumentDecorations.tsx | 2 +- src/client/views/MainOverlayTextBox.tsx | 2 +- src/client/views/MainView.tsx | 2 +- .../views/collections/CollectionBaseView.tsx | 48 ++++------------------ .../views/collections/CollectionDockingView.tsx | 2 +- .../views/collections/CollectionSchemaView.tsx | 4 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 8 ++-- src/client/views/nodes/DocumentContentsView.tsx | 1 + src/client/views/nodes/DocumentView.tsx | 11 ++--- src/client/views/nodes/FieldView.tsx | 4 +- src/client/views/nodes/KeyValuePair.tsx | 2 +- src/client/views/pdf/PDFViewer.tsx | 2 +- 14 files changed, 31 insertions(+), 65 deletions(-) (limited to 'src/client/views/nodes/DocumentContentsView.tsx') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index b04fc401a..ac8a892b8 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -344,7 +344,7 @@ export namespace Docs { {layout}
- +
`); @@ -356,7 +356,7 @@ export namespace Docs { {layout}
- +
`); @@ -379,7 +379,7 @@ export namespace Docs { {layout}
- +
`); diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 3143924fc..442187912 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -28,7 +28,6 @@ export function SetupDrag(_reference: React.RefObject, docFunc: () document.removeEventListener('pointerup', onRowUp); }; let onItemDown = async (e: React.PointerEvent) => { - // if (this.props.isSelected() || this.props.isTopMost) { if (e.button === 0) { e.stopPropagation(); if (e.shiftKey && CollectionDockingView.Instance) { @@ -38,7 +37,6 @@ export function SetupDrag(_reference: React.RefObject, docFunc: () document.addEventListener("pointerup", onRowUp); } } - //} }; return onItemDown; } diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 9d5844426..042306997 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -153,7 +153,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> @computed get Bounds(): { x: number, y: number, b: number, r: number } { return SelectionManager.SelectedDocuments().reduce((bounds, documentView) => { - if (documentView.props.isTopMost) { + if (documentView.props.renderDepth === 0) { return bounds; } let transform = (documentView.props.ScreenToLocalTransform().scale(documentView.props.ContentScaling())).inverse(); diff --git a/src/client/views/MainOverlayTextBox.tsx b/src/client/views/MainOverlayTextBox.tsx index b2cfc82c4..7363b08ef 100644 --- a/src/client/views/MainOverlayTextBox.tsx +++ b/src/client/views/MainOverlayTextBox.tsx @@ -123,7 +123,7 @@ export class MainOverlayTextBox extends React.Component this._dominus = dominus} /> diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index a72f25b99..d26e24748 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -211,7 +211,7 @@ export class MainView extends React.Component { ContentScaling={returnOne} PanelWidth={this.getPWidth} PanelHeight={this.getPHeight} - isTopMost={true} + renderDepth={0} selectOnLoad={false} focus={emptyFunction} parentActive={returnTrue} diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx index 79a9f3be0..50d1a5071 100644 --- a/src/client/views/collections/CollectionBaseView.tsx +++ b/src/client/views/collections/CollectionBaseView.tsx @@ -64,8 +64,7 @@ export class CollectionBaseView extends React.Component { active = (): boolean => { var isSelected = this.props.isSelected(); - var topMost = this.props.isTopMost; - return isSelected || this._isChildActive || topMost; + return isSelected || this._isChildActive || this.props.renderDepth === 0; } //TODO should this be observable? @@ -75,32 +74,6 @@ export class CollectionBaseView extends React.Component { this.props.whenActiveChanged(isActive); } - createsCycle(documentToAdd: Doc, containerDocument: Doc): boolean { - if (!(documentToAdd instanceof Doc)) { - return false; - } - if (StrCast(documentToAdd.layout).indexOf("CollectionView") !== -1) { - let data = DocListCast(documentToAdd.data); - for (const doc of data) { - if (this.createsCycle(doc, containerDocument)) { - return true; - } - } - } - let annots = DocListCast(documentToAdd.annotations); - for (const annot of annots) { - if (this.createsCycle(annot, containerDocument)) { - return true; - } - } - for (let containerProto: Opt = containerDocument; containerProto !== undefined; containerProto = FieldValue(containerProto.proto)) { - if (containerProto[Id] === documentToAdd[Id]) { - return true; - } - } - return false; - } - @action.bound addDocument(doc: Doc, allowDuplicates: boolean = false): boolean { var curPage = NumCast(this.props.Document.curPage, -1); @@ -109,19 +82,16 @@ export class CollectionBaseView extends React.Component { Doc.GetProto(doc).annotationOn = this.props.Document; } allowDuplicates = true; - if (!this.createsCycle(doc, this.dataDoc)) { - //TODO This won't create the field if it doesn't already exist - const value = Cast(this.dataDoc[this.props.fieldKey], listSpec(Doc)); - if (value !== undefined) { - if (allowDuplicates || !value.some(v => v instanceof Doc && v[Id] === doc[Id])) { - value.push(doc); - } - } else { - Doc.SetOnPrototype(this.dataDoc, this.props.fieldKey, new List([doc])); + //TODO This won't create the field if it doesn't already exist + const value = Cast(this.dataDoc[this.props.fieldKey], listSpec(Doc)); + if (value !== undefined) { + if (allowDuplicates || !value.some(v => v instanceof Doc && v[Id] === doc[Id])) { + value.push(doc); } - return true; + } else { + Doc.SetOnPrototype(this.dataDoc, this.props.fieldKey, new List([doc])); } - return false; + return true; } @action.bound diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 82cb5dbbb..6d2f61173 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -535,7 +535,7 @@ export class DockedFrameRenderer extends React.Component { PanelWidth={this.nativeWidth} PanelHeight={this.nativeHeight} ScreenToLocalTransform={this.ScreenToLocalTransform} - isTopMost={true} + renderDepth={0} selectOnLoad={false} parentActive={returnTrue} whenActiveChanged={emptyFunction} diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index b4158a5b1..f03afe7e0 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -104,7 +104,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { ContainingCollectionView: this.props.CollectionView, isSelected: returnFalse, select: emptyFunction, - isTopMost: false, + renderDepth: this.props.renderDepth + 1, selectOnLoad: false, ScreenToLocalTransform: Transform.Identity, focus: emptyFunction, @@ -454,7 +454,7 @@ export class CollectionSchemaPreview extends React.Component 0) { return; } e.stopPropagation(); @@ -303,7 +303,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { removeDocument: this.props.removeDocument, moveDocument: this.props.moveDocument, ScreenToLocalTransform: this.getTransform, - isTopMost: false, + renderDepth: this.props.renderDepth + 1, selectOnLoad: layoutDoc[Id] === this._selectOnLoaded, PanelWidth: layoutDoc[WidthSym], PanelHeight: layoutDoc[HeightSym], @@ -404,7 +404,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { class CollectionFreeFormOverlayView extends React.Component boolean }> { @computed get overlayView() { return (); + renderDepth={this.props.renderDepth} isSelected={this.props.isSelected} select={emptyFunction} />); } render() { return this.overlayView; @@ -416,7 +416,7 @@ class CollectionFreeFormBackgroundView extends React.Component); + renderDepth={this.props.renderDepth} isSelected={this.props.isSelected} select={emptyFunction} />); } render() { return this.props.Document.backgroundLayout ? this.backgroundView : (null); diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx index a4316c143..0da4888a1 100644 --- a/src/client/views/nodes/DocumentContentsView.tsx +++ b/src/client/views/nodes/DocumentContentsView.tsx @@ -103,6 +103,7 @@ export class DocumentContentsView extends React.Component 7) return (null); if (!this.layout && (this.props.layoutKey !== "overlayLayout" || !this.templates.length)) return (null); return boolean; moveDocument?: (doc: Doc, targetCollection: Doc, addDocument: (document: Doc) => boolean) => boolean; ScreenToLocalTransform: () => Transform; - isTopMost: boolean; + renderDepth: number; ContentScaling: () => number; PanelWidth: () => number; PanelHeight: () => number; @@ -120,7 +120,7 @@ export class DocumentView extends DocComponent(Docu public get ContentDiv() { return this._mainCont.current; } @computed get active(): boolean { return SelectionManager.IsSelected(this) || this.props.parentActive(); } - @computed get topMost(): boolean { return this.props.isTopMost; } + @computed get topMost(): boolean { return this.props.renderDepth === 0; } @computed get templates(): List { let field = this.props.Document.templates; if (field && field instanceof List) { @@ -268,7 +268,7 @@ export class DocumentView extends DocComponent(Docu e.stopPropagation(); let altKey = e.altKey; let ctrlKey = e.ctrlKey; - if (this._doubleTap && !this.props.isTopMost) { + if (this._doubleTap && !this.props.renderDepth) { this.props.addDocTab(this.props.Document, this.props.DataDoc, "inTab"); SelectionManager.DeselectAll(); this.props.Document.libraryBrush = false; @@ -436,7 +436,6 @@ export class DocumentView extends DocComponent(Docu @action addTemplate = (template: Template) => { this.templates.push(template.Layout); - this.templates = this.templates; } @action @@ -447,7 +446,6 @@ export class DocumentView extends DocComponent(Docu break; } } - this.templates = this.templates; } freezeNativeDimensions = (): void => { @@ -549,7 +547,7 @@ export class DocumentView extends DocComponent(Docu var nativeWidth = this.nativeWidth > 0 ? `${this.nativeWidth}px` : "100%"; var nativeHeight = BoolCast(this.props.Document.ignoreAspect) ? this.props.PanelHeight() / this.props.ContentScaling() : this.nativeHeight > 0 ? `${this.nativeHeight}px` : "100%"; return ( -
(Docu transform: `scale(${scaling}, ${scaling})` }} onDrop={this.onDrop} onContextMenu={this.onContextMenu} onPointerDown={this.onPointerDown} onClick={this.onClick} - onPointerEnter={this.onPointerEnter} onPointerLeave={this.onPointerLeave} > {this.contents} diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx index 8879da55f..374a523cb 100644 --- a/src/client/views/nodes/FieldView.tsx +++ b/src/client/views/nodes/FieldView.tsx @@ -33,7 +33,7 @@ export interface FieldViewProps { DataDoc: Doc; isSelected: () => boolean; select: (isCtrlPressed: boolean) => void; - isTopMost: boolean; + renderDepth: number; selectOnLoad: boolean; addDocument?: (document: Doc, allowDuplicates?: boolean) => boolean; addDocTab: (document: Doc, dataDoc: Doc, where: string) => void; @@ -97,7 +97,7 @@ export class FieldView extends React.Component { // ContentScaling={returnOne} // PanelWidth={returnHundred} // PanelHeight={returnHundred} - // isTopMost={true} //TODO Why is this top most? + // renderDepth={0} //TODO Why is renderDepth reset? // selectOnLoad={false} // focus={emptyFunction} // isSelected={this.props.isSelected} diff --git a/src/client/views/nodes/KeyValuePair.tsx b/src/client/views/nodes/KeyValuePair.tsx index 3e03e7e75..3dda81db7 100644 --- a/src/client/views/nodes/KeyValuePair.tsx +++ b/src/client/views/nodes/KeyValuePair.tsx @@ -32,7 +32,7 @@ export class KeyValuePair extends React.Component { fieldKey: this.props.keyName, isSelected: returnFalse, select: emptyFunction, - isTopMost: false, + renderDepth: 1, selectOnLoad: false, active: returnFalse, whenActiveChanged: emptyFunction, diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index b9e93b4da..10c66d318 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -492,7 +492,7 @@ interface IAnnotationProps { // 1} // PanelWidth={() => NumCast(this.props.parent.props.parent.Document.nativeWidth)} // PanelHeight={() => NumCast(this.props.parent.props.parent.Document.nativeHeight)} -- cgit v1.2.3-70-g09d2 From 4e00ff1c268f0c5453b448dd1810e14c47b37969 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Fri, 28 Jun 2019 16:27:38 -0400 Subject: test2 --- src/client/views/nodes/DocumentContentsView.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/client/views/nodes/DocumentContentsView.tsx') diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx index 0da4888a1..240b21714 100644 --- a/src/client/views/nodes/DocumentContentsView.tsx +++ b/src/client/views/nodes/DocumentContentsView.tsx @@ -52,7 +52,8 @@ export class DocumentContentsView extends React.Component" : + "null" : + // "" : KeyValueBox.LayoutString(layoutDoc.proto ? "proto" : ""); } else if (typeof layout === "string") { return layout; -- cgit v1.2.3-70-g09d2 From 8ef971485492e3dc461cd93b2ae89e01b9995741 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Fri, 28 Jun 2019 16:57:46 -0400 Subject: undo tests --- src/client/views/nodes/DocumentContentsView.tsx | 3 +-- src/client/views/nodes/KeyValueBox.tsx | 1 - src/client/views/pdf/PDFViewer.tsx | 3 +-- src/new_fields/Doc.ts | 1 - 4 files changed, 2 insertions(+), 6 deletions(-) (limited to 'src/client/views/nodes/DocumentContentsView.tsx') diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx index 240b21714..0da4888a1 100644 --- a/src/client/views/nodes/DocumentContentsView.tsx +++ b/src/client/views/nodes/DocumentContentsView.tsx @@ -52,8 +52,7 @@ export class DocumentContentsView extends React.Component" : + "" : KeyValueBox.LayoutString(layoutDoc.proto ? "proto" : ""); } else if (typeof layout === "string") { return layout; diff --git a/src/client/views/nodes/KeyValueBox.tsx b/src/client/views/nodes/KeyValueBox.tsx index eee4ec670..0e798d291 100644 --- a/src/client/views/nodes/KeyValueBox.tsx +++ b/src/client/views/nodes/KeyValueBox.tsx @@ -207,7 +207,6 @@ export class KeyValueBox extends React.Component { } render() { - return null; let dividerDragger = this.splitPercentage === 0 ? (null) :
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index 380ba3c45..a645b0041 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -1,4 +1,4 @@ -import { action, computed, IReactionDisposer, observable, reaction, runInAction, trace } from "mobx"; +import { action, computed, IReactionDisposer, observable, reaction, runInAction } from "mobx"; import { observer } from "mobx-react"; import * as Pdfjs from "pdfjs-dist"; import "pdfjs-dist/web/pdf_viewer.css"; @@ -620,7 +620,6 @@ class Viewer extends React.Component { } render() { - trace(); let compiled = this._script; return (
diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index 0340806ef..27dcfba08 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -281,7 +281,6 @@ export namespace Doc { } export function expandTemplateLayout(templateLayoutDoc: Doc, dataDoc?: Doc) { - return templateLayoutDoc; let resolvedDataDoc = (templateLayoutDoc !== dataDoc) ? dataDoc : undefined; if (!dataDoc || !(templateLayoutDoc && !(Cast(templateLayoutDoc.layout, Doc) instanceof Doc) && resolvedDataDoc && resolvedDataDoc !== templateLayoutDoc)) { return templateLayoutDoc; -- cgit v1.2.3-70-g09d2 From 74e4909a77ac143ecdb1d038ad182aae9c710129 Mon Sep 17 00:00:00 2001 From: Sam Wilkins Date: Wed, 3 Jul 2019 22:15:25 -0400 Subject: implemented directory import routine --- src/client/documents/Documents.ts | 57 ++++++++- src/client/util/Import & Export/ImageImporter.tsx | 67 +++++++++++ src/client/util/Import & Export/ImportBox.tsx | 134 +++++++++++++++++++++ src/client/util/SelectionManager.ts | 2 +- src/client/views/MainView.tsx | 3 + src/client/views/collections/CollectionSubView.tsx | 46 +------ src/client/views/nodes/DocumentContentsView.tsx | 3 +- 7 files changed, 265 insertions(+), 47 deletions(-) create mode 100644 src/client/util/Import & Export/ImageImporter.tsx create mode 100644 src/client/util/Import & Export/ImportBox.tsx (limited to 'src/client/views/nodes/DocumentContentsView.tsx') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 7d7a1f02a..5d637dd3a 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -36,6 +36,7 @@ import { UndoManager } from "../util/UndoManager"; import { RouteStore } from "../../server/RouteStore"; import { LinkManager } from "../util/LinkManager"; import { DocumentManager } from "../util/DocumentManager"; +import ImportBox from "../util/Import & Export/ImportBox"; var requestImageSize = require('../util/request-image-size'); var path = require('path'); @@ -51,7 +52,8 @@ export enum DocTypes { KVP = "kvp", VID = "video", AUDIO = "audio", - LINK = "link" + LINK = "link", + IMPORT = "import" } export interface DocumentOptions { @@ -127,6 +129,7 @@ export namespace Docs { let audioProto: Doc; let pdfProto: Doc; let iconProto: Doc; + let importProto: Doc; // let linkProto: Doc; const textProtoId = "textProto"; const histoProtoId = "histoProto"; @@ -138,6 +141,7 @@ export namespace Docs { const videoProtoId = "videoProto"; const audioProtoId = "audioProto"; const iconProtoId = "iconProto"; + const importProtoId = "importProto"; // const linkProtoId = "linkProto"; export function initProtos(): Promise { @@ -152,6 +156,7 @@ export namespace Docs { audioProto = fields[audioProtoId] as Doc || CreateAudioPrototype(); pdfProto = fields[pdfProtoId] as Doc || CreatePdfPrototype(); iconProto = fields[iconProtoId] as Doc || CreateIconPrototype(); + importProto = fields[importProtoId] as Doc || CreateImportPrototype(); }); } @@ -174,6 +179,11 @@ export namespace Docs { return imageProto; } + function CreateImportPrototype(): Doc { + let importProto = setupPrototypeOptions(importProtoId, "IMPORT_PROTO", ImportBox.LayoutString(), { x: 0, y: 0, width: 600, height: 600, type: DocTypes.IMPORT }); + return importProto; + } + function CreateHistogramPrototype(): Doc { let histoProto = setupPrototypeOptions(histoProtoId, "HISTO PROTO", CollectionView.LayoutString("annotations"), { x: 0, y: 0, width: 300, height: 300, backgroundColor: "black", backgroundLayout: HistogramBox.LayoutString(), type: DocTypes.HIST }); @@ -261,6 +271,10 @@ export namespace Docs { return CreateInstance(audioProto, new AudioField(new URL(url)), options); } + export function DirectoryImportDocument(options: DocumentOptions = {}) { + return CreateInstance(importProto, "", options); + } + export function HistogramDocument(histoOp: HistogramOperation, options: DocumentOptions = {}) { return CreateInstance(histoProto, new HistogramField(histoOp), options); } @@ -333,6 +347,47 @@ export namespace Docs { return CreateInstance(collProto, new List(documents), { ...options, viewType: CollectionViewType.Docking, dockingConfig: config }, id); } + export async function getDocumentFromType(type: string, path: string, options: DocumentOptions, addDocument?: (document: Doc, allowDuplicates?: boolean) => boolean): Promise> { + let ctor: ((path: string, options: DocumentOptions) => (Doc | Promise)) | undefined = undefined; + if (type.indexOf("image") !== -1) { + ctor = Docs.ImageDocument; + } + if (type.indexOf("video") !== -1) { + ctor = Docs.VideoDocument; + } + if (type.indexOf("audio") !== -1) { + ctor = Docs.AudioDocument; + } + if (type.indexOf("pdf") !== -1) { + ctor = Docs.PdfDocument; + options.nativeWidth = 1200; + } + if (type.indexOf("excel") !== -1) { + ctor = Docs.DBDocument; + options.dropAction = "copy"; + } + if (type.indexOf("html") !== -1) { + if (path.includes(window.location.hostname)) { + let s = path.split('/'); + let id = s[s.length - 1]; + DocServer.GetRefField(id).then(field => { + if (field instanceof Doc) { + let alias = Doc.MakeAlias(field); + alias.x = options.x || 0; + alias.y = options.y || 0; + alias.width = options.width || 300; + alias.height = options.height || options.width || 300; + addDocument && addDocument(alias, false); + } + }); + return undefined; + } + ctor = Docs.WebDocument; + options = { height: options.width, ...options, title: path, nativeWidth: undefined }; + } + return ctor ? ctor(path, options) : undefined; + } + export function CaptionDocument(doc: Doc) { const captionDoc = Doc.MakeAlias(doc); captionDoc.overlayLayout = FixedCaption(); diff --git a/src/client/util/Import & Export/ImageImporter.tsx b/src/client/util/Import & Export/ImageImporter.tsx new file mode 100644 index 000000000..d664f6487 --- /dev/null +++ b/src/client/util/Import & Export/ImageImporter.tsx @@ -0,0 +1,67 @@ +import "fs"; +import React = require("react"); +import { Doc } from "../../../new_fields/Doc"; +import { DocServer } from "../../DocServer"; +import { RouteStore } from "../../../server/RouteStore"; +import { action } from "mobx"; +import { Docs } from "../../documents/Documents"; +import { FieldViewProps } from "../../views/nodes/FieldView"; + +interface ImageImporterProps { + addSchema: (imageDocs: Doc[]) => void; +} + +export default class BulkImporter extends React.Component { + private selector = React.createRef(); + + handleSelection = async (e: React.ChangeEvent) => { + let promises: Promise[] = []; + let docs: Doc[] = []; + + let files = e.target.files; + if (!files) return; + + for (let i = 0; i < files.length; i++) { + let target = files.item(i); + + if (target === null) { + continue; + } + + let type = target.type; + let formData = new FormData(); + formData.append('file', target); + let dropFileName = target ? target.name : "-empty-"; + + let prom = fetch(DocServer.prepend(RouteStore.upload), { + method: 'POST', + body: formData + }).then(async (res: Response) => { + (await res.json()).map(action((file: any) => { + let path = window.location.origin + file; + let docPromise = Docs.getDocumentFromType(type, path, { nativeWidth: 300, width: 300, title: dropFileName }); + docPromise.then(doc => doc && docs.push(doc)); + })); + }); + promises.push(prom); + } + + await Promise.all(promises); + + let parent = Docs.SchemaDocument(["title", "data"], docs, { width: 300, height: 300, title: "Bulk Import from Directory" }); + } + + componentDidMount() { + this.selector.current!.setAttribute("directory", "true"); + this.selector.current!.setAttribute("webkitdirectory", "true"); + } + + render() { + return ( +
+ +
+ ); + } + +} \ No newline at end of file diff --git a/src/client/util/Import & Export/ImportBox.tsx b/src/client/util/Import & Export/ImportBox.tsx new file mode 100644 index 000000000..630911710 --- /dev/null +++ b/src/client/util/Import & Export/ImportBox.tsx @@ -0,0 +1,134 @@ +import "fs"; +import React = require("react"); +import { Doc } from "../../../new_fields/Doc"; +import { DocServer } from "../../DocServer"; +import { RouteStore } from "../../../server/RouteStore"; +import { action, observable } from "mobx"; +import { FieldViewProps, FieldView } from "../../views/nodes/FieldView"; +import Measure, { ContentRect } from "react-measure"; +import { library } from '@fortawesome/fontawesome-svg-core'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { faArrowUp } from '@fortawesome/free-solid-svg-icons'; +import { Docs, DocumentOptions } from "../../documents/Documents"; + +interface ImageImporterProps { + addSchema: (imageDocs: Doc[]) => void; +} + +export default class ImportBox extends React.Component { + @observable private top = 0; + @observable private left = 0; + private dimensions = 50; + + constructor(props: FieldViewProps) { + super(props); + library.add(faArrowUp); + } + + public static LayoutString() { return FieldView.LayoutString(ImportBox); } + + private selector = React.createRef(); + + handleSelection = async (e: React.ChangeEvent) => { + let promises: Promise[] = []; + let docs: Doc[] = []; + + let files = e.target.files; + if (!files || files.length === 0) return; + + let directory = (files.item(0) as any).webkitRelativePath.split("/", 1); + + for (let i = 0; i < files.length; i++) { + let uploaded_file = files.item(i); + + if (!uploaded_file) { + continue; + } + + let formData = new FormData(); + formData.append('file', uploaded_file); + let dropFileName = uploaded_file ? uploaded_file.name : "-empty-"; + let type = uploaded_file.type; + + let prom = fetch(DocServer.prepend(RouteStore.upload), { + method: 'POST', + body: formData + }).then(async (res: Response) => { + (await res.json()).map(action((file: any) => { + let path = DocServer.prepend(file); + let docPromise = Docs.getDocumentFromType(type, path, { nativeWidth: 300, width: 300, title: dropFileName }); + docPromise.then(doc => doc && docs.push(doc)); + })); + }); + promises.push(prom); + } + + await Promise.all(promises); + + let doc = this.props.Document; + let options: DocumentOptions = { title: `Import of ${directory}`, width: 500, height: 500, x: Doc.GetT(doc, "x", "number"), y: Doc.GetT(doc, "y", "number") }; + let parent = this.props.ContainingCollectionView; + if (parent) { + let importContainer = Docs.StackingDocument(docs, options); + Doc.AddDocToList(Doc.GetProto(parent.props.Document), "data", importContainer); + this.props.removeDocument && this.props.removeDocument(doc); + } + } + + componentDidMount() { + this.selector.current!.setAttribute("directory", "true"); + this.selector.current!.setAttribute("webkitdirectory", "true"); + } + + @action + preserveCentering = (rect: ContentRect) => { + let bounds = rect.offset!; + if (bounds.width === 0 || bounds.height === 0) { + return; + } + let offset = this.dimensions / 2; + this.left = bounds.width / 2 - offset; + this.top = bounds.height / 2 - offset; + } + + render() { + let dimensions = 50; + return ( + + {({ measureRef }) => +
+ +