From 63129c244fc2b9a5c60e6a94b864895641b86f57 Mon Sep 17 00:00:00 2001 From: bob Date: Wed, 20 Nov 2019 16:59:40 -0500 Subject: lots of changes to make rendering more efficient (fewer mobx invalidations). made selection and collecitonviews use an observableMap that works now. --- src/client/views/nodes/FieldView.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/client/views/nodes/FieldView.tsx') diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx index 5108954bb..c93746773 100644 --- a/src/client/views/nodes/FieldView.tsx +++ b/src/client/views/nodes/FieldView.tsx @@ -31,7 +31,7 @@ export interface FieldViewProps { Document: Doc; DataDoc?: Doc; onClick?: ScriptField; - isSelected: () => boolean; + isSelected: (outsideReaction?: boolean) => boolean; select: (isCtrlPressed: boolean) => void; renderDepth: number; addDocument?: (document: Doc) => boolean; @@ -40,7 +40,7 @@ export interface FieldViewProps { removeDocument?: (document: Doc) => boolean; moveDocument?: (document: Doc, targetCollection: Doc, addDocument: (document: Doc) => boolean) => boolean; ScreenToLocalTransform: () => Transform; - active: () => boolean; + active: (outsideReaction?: boolean) => boolean; whenActiveChanged: (isActive: boolean) => void; focus: (doc: Doc) => void; PanelWidth: () => number; -- cgit v1.2.3-70-g09d2 From 74839056c8fccb216ee682c642771ab101b43d35 Mon Sep 17 00:00:00 2001 From: bob Date: Wed, 4 Dec 2019 14:34:17 -0500 Subject: from last --- src/client/views/nodes/FieldView.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/client/views/nodes/FieldView.tsx') diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx index c93746773..048960c5e 100644 --- a/src/client/views/nodes/FieldView.tsx +++ b/src/client/views/nodes/FieldView.tsx @@ -53,7 +53,7 @@ export interface FieldViewProps { @observer export class FieldView extends React.Component { public static LayoutString(fieldType: { name: string }, fieldStr: string) { - return `<${fieldType.name} {...props} fieldKey={"${fieldStr}"}/>`; //e.g., "" + return `<${fieldType.name} {...props} fieldKey={'${fieldStr}'}/>`; //e.g., "" } @computed -- cgit v1.2.3-70-g09d2 From 968d678e8aeb6f57cc892e3fe789067a8246c5fe Mon Sep 17 00:00:00 2001 From: bob Date: Wed, 4 Dec 2019 17:47:28 -0500 Subject: started to add paths --- src/client/documents/Documents.ts | 5 +-- src/client/util/RichTextSchema.tsx | 3 +- src/client/views/CollectionLinearView.tsx | 1 + src/client/views/MainView.tsx | 11 ++++--- src/client/views/OverlayView.tsx | 1 + .../views/collections/CollectionDockingView.tsx | 38 +++++++++++++--------- .../views/collections/CollectionSchemaView.tsx | 1 + .../views/collections/CollectionStackingView.tsx | 1 + .../views/collections/CollectionTreeView.tsx | 36 +++++++++++--------- .../collectionFreeForm/CollectionFreeFormView.tsx | 1 + .../views/nodes/ContentFittingDocumentView.tsx | 4 ++- src/client/views/nodes/DocumentView.tsx | 12 ++++--- src/client/views/nodes/FieldView.tsx | 1 + src/client/views/nodes/FormattedTextBoxComment.tsx | 3 +- .../views/presentationview/PresElementBox.tsx | 3 +- src/client/views/search/SearchItem.tsx | 3 +- 16 files changed, 78 insertions(+), 46 deletions(-) (limited to 'src/client/views/nodes/FieldView.tsx') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index e0f2858ba..5d5bdfcbd 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -534,7 +534,8 @@ export namespace Docs { export type DocConfig = { doc: Doc, - initialWidth?: number + initialWidth?: number, + path?: Doc[] }; export function StandardCollectionDockingDocument(configs: Array, options: DocumentOptions, id?: string, type: string = "row") { @@ -543,7 +544,7 @@ export namespace Docs { { type: type, content: [ - ...configs.map(config => CollectionDockingView.makeDocumentConfig(config.doc, undefined, config.initialWidth)) + ...configs.map(config => CollectionDockingView.makeDocumentConfig(config.doc, undefined, config.initialWidth, config.path)) ] } ] diff --git a/src/client/util/RichTextSchema.tsx b/src/client/util/RichTextSchema.tsx index 3b786e61d..4612f2885 100644 --- a/src/client/util/RichTextSchema.tsx +++ b/src/client/util/RichTextSchema.tsx @@ -761,8 +761,9 @@ export class DashDocView { this._dashSpan.style.width = this._outer.style.width = dashDoc[WidthSym]() + "px"; }); ReactDOM.render( this.openWorkspace(mainDoc), 0); @@ -271,6 +270,7 @@ export class MainView extends React.Component { {!mainContainer ? (null) : this.flyoutWidth; - addDocTabFunc = (doc: Doc, data: Opt, where: string) => { + addDocTabFunc = (doc: Doc, data: Opt, where: string, libraryPath?: Doc[]) => { if (where === "close") { return CollectionDockingView.CloseRightSplit(doc); } @@ -346,7 +346,7 @@ export class MainView extends React.Component { this.openWorkspace(doc); return true; } else { - return CollectionDockingView.AddRightSplit(doc, undefined); + return CollectionDockingView.AddRightSplit(doc, undefined, undefined, libraryPath); } } mainContainerXf = () => new Transform(0, -this._buttonBarHeight, 1); @@ -363,6 +363,7 @@ export class MainView extends React.Component { { @observable public static Instances: CollectionDockingView[] = []; @computed public static get Instance() { return CollectionDockingView.Instances[0]; } - public static makeDocumentConfig(document: Doc, dataDoc: Doc | undefined, width?: number) { + public static makeDocumentConfig(document: Doc, dataDoc: Doc | undefined, width?: number, libraryPath?: Doc[]) { return { type: 'react-component', component: 'DocumentFrameRenderer', @@ -47,7 +47,8 @@ export class CollectionDockingView extends React.Component d[Id]) : [] //collectionDockingView: CollectionDockingView.Instance } }; @@ -95,12 +96,12 @@ export class CollectionDockingView extends React.Component { + public AddTab = (stack: any, document: Doc, dataDocument: Doc | undefined, libraryPath?: Doc[]) => { Doc.GetProto(document).lastOpened = new DateField; - const docContentConfig = CollectionDockingView.makeDocumentConfig(document, dataDocument); + const docContentConfig = CollectionDockingView.makeDocumentConfig(document, dataDocument, undefined, libraryPath); if (stack === undefined) { let stack: any = this._goldenLayout.root; while (!stack.isStack) { @@ -427,10 +428,6 @@ export class CollectionDockingView extends React.Component, dragSpan); ReactDOM.render(, gearSpan); - // ReactDOM.render( { - // where === "onRight" ? CollectionDockingView.AddRightSplit(doc, dataDoc) : CollectionDockingView.Instance.AddTab(stack, doc, dataDoc); - // return true; - // }} />, upDiv); tab.reactComponents = [dragSpan, gearSpan, upDiv]; tab.element.append(dragSpan); tab.element.append(gearSpan); @@ -532,11 +529,13 @@ interface DockedFrameProps { documentId: FieldId; dataDocumentId: FieldId; glContainer: any; + libraryPath: (FieldId[]) //collectionDockingView: CollectionDockingView } @observer export class DockedFrameRenderer extends React.Component { _mainCont: HTMLDivElement | null = null; + @observable private _libraryPath: Doc[] = []; @observable private _panelWidth = 0; @observable private _panelHeight = 0; @observable private _document: Opt; @@ -554,6 +553,14 @@ export class DockedFrameRenderer extends React.Component { DocServer.GetRefField(this.props.dataDocumentId).then(action((f: Opt) => this._dataDoc = f as Doc)); } })); + this.props.libraryPath && this.setupLibraryPath(); + } + + async setupLibraryPath() { + Promise.all(this.props.libraryPath.map(async docid => { + let d = await DocServer.GetRefField(docid); + return d instanceof Doc ? d : undefined + })).then(action((list: (Doc | undefined)[]) => this._libraryPath = list.filter(d => d).map(d => d as Doc))); } /** @@ -640,17 +647,17 @@ export class DockedFrameRenderer extends React.Component { get previewPanelCenteringOffset() { return this.nativeWidth() && !this.layoutDoc!.ignoreAspect ? (this._panelWidth - this.nativeWidth() * this.contentScaling()) / 2 : 0; } get widthpercent() { return this.nativeWidth() && !this.layoutDoc!.ignoreAspect ? `${(this.nativeWidth() * this.contentScaling()) / this.panelWidth() * 100}%` : undefined; } - addDocTab = (doc: Doc, dataDoc: Opt, location: string) => { + addDocTab = (doc: Doc, dataDoc: Opt, location: string, libraryPath?: Doc[]) => { SelectionManager.DeselectAll(); if (doc.dockingConfig) { MainView.Instance.openWorkspace(doc); return true; } else if (location === "onRight") { - return CollectionDockingView.AddRightSplit(doc, dataDoc); + return CollectionDockingView.AddRightSplit(doc, dataDoc, undefined, libraryPath); } else if (location === "close") { return CollectionDockingView.CloseRightSplit(doc); } else { - return CollectionDockingView.Instance.AddTab(this._stack, doc, dataDoc); + return CollectionDockingView.Instance.AddTab(this._stack, doc, dataDoc, libraryPath); } } @@ -659,6 +666,7 @@ export class DockedFrameRenderer extends React.Component { const document = this._document; const resolvedDataDoc = document.layout instanceof Doc ? document : this._dataDoc; return doc) { doc) { return boolean; + addDocTab: (doc: Doc, dataDoc: Doc | undefined, where: string, libraryPath?: Doc[]) => boolean; pinToPres: (document: Doc) => void; panelWidth: () => number; panelHeight: () => number; @@ -95,8 +96,8 @@ class TreeView extends React.Component { @computed get MAX_EMBED_HEIGHT() { return NumCast(this.props.document.maxEmbedHeight, 300); } @computed get dataDoc() { return this.templateDataDoc ? this.templateDataDoc : this.props.document; } @computed get fieldKey() { - const splits = StrCast(Doc.LayoutField(this.props.document)).split("fieldKey={\""); - return splits.length > 1 ? splits[1].split("\"")[0] : "data"; + const splits = StrCast(Doc.LayoutField(this.props.document)).split("fieldKey={\'"); + return splits.length > 1 ? splits[1].split("\'")[0] : "data"; } childDocList(field: string) { const layout = Doc.LayoutField(this.props.document) instanceof Doc ? Doc.LayoutField(this.props.document) as Doc : undefined; @@ -120,7 +121,7 @@ class TreeView extends React.Component { } @undoBatch delete = () => this.props.deleteDoc(this.props.document); - @undoBatch openRight = () => this.props.addDocTab(this.props.document, this.templateDataDoc, "onRight"); + @undoBatch openRight = () => this.props.addDocTab(this.props.document, this.templateDataDoc, "onRight", this.props.libraryPath); @undoBatch indent = () => this.props.addDocument(this.props.document) && this.delete(); @undoBatch move = (doc: Doc, target: Doc, addDoc: (doc: Doc) => boolean) => { return this.props.document !== target && this.props.deleteDoc(doc) && addDoc(doc); @@ -194,8 +195,8 @@ class TreeView extends React.Component { ContextMenu.Instance.addItem({ description: "Clear All", event: () => Doc.GetProto(CurrentUserUtils.UserDocument.recentlyClosed as Doc).data = new List(), icon: "plus" }); } else if (this.props.document !== CurrentUserUtils.UserDocument.workspaces) { ContextMenu.Instance.addItem({ description: "Pin to Presentation", event: () => this.props.pinToPres(this.props.document), icon: "tv" }); - ContextMenu.Instance.addItem({ description: "Open Tab", event: () => this.props.addDocTab(this.props.document, this.templateDataDoc, "inTab"), icon: "folder" }); - ContextMenu.Instance.addItem({ description: "Open Right", event: () => this.props.addDocTab(this.props.document, this.templateDataDoc, "onRight"), icon: "caret-square-right" }); + ContextMenu.Instance.addItem({ description: "Open Tab", event: () => this.props.addDocTab(this.props.document, this.templateDataDoc, "inTab", this.props.libraryPath), icon: "folder" }); + ContextMenu.Instance.addItem({ description: "Open Right", event: () => this.props.addDocTab(this.props.document, this.templateDataDoc, "onRight", this.props.libraryPath), icon: "caret-square-right" }); if (DocumentManager.Instance.getDocumentViews(this.dataDoc).length) { ContextMenu.Instance.addItem({ description: "Focus", event: () => (view => view && view.props.focus(this.props.document, true))(DocumentManager.Instance.getFirstDocumentView(this.dataDoc)), icon: "camera" }); } @@ -286,7 +287,7 @@ class TreeView extends React.Component { DocListCast(contents), this.props.treeViewId, doc, undefined, key, this.props.containingCollection, this.props.prevSibling, addDoc, remDoc, this.move, this.props.dropAction, this.props.addDocTab, this.props.pinToPres, this.props.ScreenToLocalTransform, this.props.outerXf, this.props.active, this.props.panelWidth, this.props.ChromeHeight, this.props.renderDepth, this.props.hideHeaderFields, this.props.preventTreeViewOpen, - [...this.props.renderedIds, doc[Id]]); + [...this.props.renderedIds, doc[Id]], this.props.libraryPath); } else { contentElement = { this.templateDataDoc, expandKey, this.props.containingCollection, this.props.prevSibling, addDoc, remDoc, this.move, this.props.dropAction, this.props.addDocTab, this.props.pinToPres, this.props.ScreenToLocalTransform, this.props.outerXf, this.props.active, this.props.panelWidth, this.props.ChromeHeight, this.props.renderDepth, this.props.hideHeaderFields, this.props.preventTreeViewOpen, - [...this.props.renderedIds, this.props.document[Id]])} + [...this.props.renderedIds, this.props.document[Id]], this.props.libraryPath)} ; } else if (this.treeViewExpandedView === "fields") { return
    @@ -343,6 +344,7 @@ class TreeView extends React.Component { { renderDepth: number, hideHeaderFields: () => boolean, preventTreeViewOpen: boolean, - renderedIds: string[] + renderedIds: string[], + libraryPath: Doc[] | undefined ) { const viewSpecScript = Cast(containingCollection.viewSpecScript, ScriptField); if (viewSpecScript) { @@ -499,9 +502,9 @@ class TreeView extends React.Component { } const indent = i === 0 ? undefined : () => { - if (StrCast(docs[i - 1].layout).indexOf("fieldKey") !== -1) { - const fieldKeysub = StrCast(docs[i - 1].layout).split("fieldKey")[1]; - const fieldKey = fieldKeysub.split("\"")[1]; + if (StrCast(docs[i - 1].layout).indexOf('fieldKey') !== -1) { + const fieldKeysub = StrCast(docs[i - 1].layout).split('fieldKey')[1]; + const fieldKey = fieldKeysub.split("\'")[1]; if (fieldKey && Cast(docs[i - 1][fieldKey], listSpec(Doc)) !== undefined) { Doc.AddDocToList(docs[i - 1], fieldKey, child); docs[i - 1].treeViewOpen = true; @@ -510,9 +513,9 @@ class TreeView extends React.Component { } }; const outdent = !parentCollectionDoc ? undefined : () => { - if (StrCast(parentCollectionDoc.layout).indexOf("fieldKey") !== -1) { - const fieldKeysub = StrCast(parentCollectionDoc.layout).split("fieldKey")[1]; - const fieldKey = fieldKeysub.split("\"")[1]; + if (StrCast(parentCollectionDoc.layout).indexOf('fieldKey') !== -1) { + const fieldKeysub = StrCast(parentCollectionDoc.layout).split('fieldKey')[1]; + const fieldKey = fieldKeysub.split("\'")[1]; Doc.AddDocToList(parentCollectionDoc, fieldKey, child, parentPrevSibling, false); parentCollectionDoc.treeViewOpen = true; remove(child); @@ -529,6 +532,7 @@ class TreeView extends React.Component { return !(child instanceof Doc) ? (null) : BoolCast(this.props.Document.hideHeaderFields), - BoolCast(this.props.Document.preventTreeViewOpen), []) + BoolCast(this.props.Document.preventTreeViewOpen), [], this.props.LibraryPath) }
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index c69b264c4..c3e064da5 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -627,6 +627,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { ...this.props, DataDoc: childData, Document: childLayout, + LibraryPath: this.props.LibraryPath ? [...this.props.LibraryPath, this.props.Document] : [], layoutKey: undefined, ruleProvider: this.Document.isRuleProvider && childLayout.type !== DocumentType.TEXT ? this.props.Document : this.props.ruleProvider, //bcz: hack! - currently ruleProviders apply to documents in nested colleciton, not direct children of themselves onClick: undefined, // this.props.onClick, // bcz: check this out -- I don't think we want to inherit click handlers, or we at least need a way to ignore them diff --git a/src/client/views/nodes/ContentFittingDocumentView.tsx b/src/client/views/nodes/ContentFittingDocumentView.tsx index efc907f9b..86fab0ba0 100644 --- a/src/client/views/nodes/ContentFittingDocumentView.tsx +++ b/src/client/views/nodes/ContentFittingDocumentView.tsx @@ -17,6 +17,7 @@ import { CollectionView } from "../collections/CollectionView"; interface ContentFittingDocumentViewProps { Document?: Doc; DataDocument?: Doc; + LibraryPath: Doc[]; childDocs?: Doc[]; renderDepth: number; fitToBox?: boolean; @@ -85,8 +86,9 @@ export class ContentFittingDocumentView extends React.Component ; Document: Doc; DataDoc?: Doc; + LibraryPath: Doc[]; fitToBox?: boolean; onClick?: ScriptField; addDocument?: (doc: Doc) => boolean; @@ -70,7 +71,7 @@ export interface DocumentViewProps { parentActive: (outsideReaction: boolean) => boolean; whenActiveChanged: (isActive: boolean) => void; bringToFront: (doc: Doc, sendToBack?: boolean) => void; - addDocTab: (doc: Doc, dataDoc: Doc | undefined, where: string) => boolean; + addDocTab: (doc: Doc, dataDoc: Doc | undefined, where: string, libraryPath?: Doc[]) => boolean; pinToPres: (document: Doc) => void; zoomToScale: (scale: number) => void; backgroundColor: (doc: Doc) => string | undefined; @@ -401,9 +402,9 @@ export class DocumentView extends DocComponent(Docu const cm = ContextMenu.Instance; const subitems: ContextMenuProps[] = []; - subitems.push({ description: "Open Full Screen", event: () => CollectionDockingView.Instance && CollectionDockingView.Instance.OpenFullScreen(this), icon: "desktop" }); - subitems.push({ description: "Open Tab ", event: () => this.props.addDocTab(this.props.Document, this.props.DataDoc, "inTab"), icon: "folder" }); - subitems.push({ description: "Open Right ", event: () => this.props.addDocTab(this.props.Document, this.props.DataDoc, "onRight"), icon: "caret-square-right" }); + subitems.push({ description: "Open Full Screen", event: () => CollectionDockingView.Instance && CollectionDockingView.Instance.OpenFullScreen(this, this.props.LibraryPath), icon: "desktop" }); + subitems.push({ description: "Open Tab ", event: () => this.props.addDocTab(this.props.Document, this.props.DataDoc, "inTab", this.props.LibraryPath), icon: "folder" }); + subitems.push({ description: "Open Right ", event: () => this.props.addDocTab(this.props.Document, this.props.DataDoc, "onRight", this.props.LibraryPath), icon: "caret-square-right" }); subitems.push({ description: "Open Alias Tab ", event: () => this.props.addDocTab(Doc.MakeAlias(this.props.Document), this.props.DataDoc, "inTab"), icon: "folder" }); subitems.push({ description: "Open Alias Right", event: () => this.props.addDocTab(Doc.MakeAlias(this.props.Document), this.props.DataDoc, "onRight"), icon: "caret-square-right" }); subitems.push({ description: "Open Fields ", event: () => this.props.addDocTab(Docs.Create.KVPDocument(this.props.Document, { width: 300, height: 300 }), undefined, "onRight"), icon: "layer-group" }); @@ -527,6 +528,8 @@ export class DocumentView extends DocComponent(Docu SelectionManager.SelectDoc(this, false); } }); + let path = this.props.LibraryPath.reduce((p: string, d: Doc) => p + "/" + (Doc.AreProtosEqual(d, (Doc.UserDoc().LibraryBtn as Doc).sourcePanel as Doc) ? "" : d.title), ""); + cm.addItem({ description: `path: ${path}`, event: () => { }, icon: "check" }) } // does Document set a layout prop @@ -552,6 +555,7 @@ export class DocumentView extends DocComponent(Docu ContainingCollectionDoc={this.props.ContainingCollectionDoc} Document={this.props.Document} fitToBox={this.props.fitToBox} + LibraryPath={this.props.LibraryPath} addDocument={this.props.addDocument} removeDocument={this.props.removeDocument} moveDocument={this.props.moveDocument} diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx index 048960c5e..ce1c468ad 100644 --- a/src/client/views/nodes/FieldView.tsx +++ b/src/client/views/nodes/FieldView.tsx @@ -30,6 +30,7 @@ export interface FieldViewProps { ruleProvider: Doc | undefined; Document: Doc; DataDoc?: Doc; + LibraryPath: Doc[]; onClick?: ScriptField; isSelected: (outsideReaction?: boolean) => boolean; select: (isCtrlPressed: boolean) => void; diff --git a/src/client/views/nodes/FormattedTextBoxComment.tsx b/src/client/views/nodes/FormattedTextBoxComment.tsx index 2ec30e3b3..9f1dd4aec 100644 --- a/src/client/views/nodes/FormattedTextBoxComment.tsx +++ b/src/client/views/nodes/FormattedTextBoxComment.tsx @@ -177,8 +177,9 @@ export class FormattedTextBoxComment { } catch (e) { } if (target) { ReactDOM.render((P width: propDocWidth === 0 ? "auto" : propDocWidth * scale(), }}> { onPointerEnter={action(() => this._displayDim = this._useIcons ? 50 : Number(SEARCH_THUMBNAIL_SIZE))} onPointerLeave={action(() => this._displayDim = 50)} > Date: Thu, 12 Dec 2019 15:02:22 -0500 Subject: major changes to drag and drop --- src/client/northstar/dash-nodes/HistogramBox.tsx | 12 +- src/client/util/DocumentManager.ts | 4 +- src/client/util/DragManager.ts | 386 ++++++++------------- src/client/util/LinkManager.ts | 6 +- src/client/views/CollectionLinearView.tsx | 2 +- src/client/views/DocComponent.tsx | 2 +- src/client/views/DocumentButtonBar.tsx | 37 +- src/client/views/DocumentDecorations.tsx | 2 +- src/client/views/MainView.tsx | 2 +- src/client/views/OverlayView.tsx | 2 - src/client/views/TemplateMenu.tsx | 11 +- .../views/collections/CollectionDockingView.tsx | 20 +- .../collections/CollectionMasonryViewFieldRow.tsx | 14 +- .../views/collections/CollectionSchemaCells.tsx | 21 +- .../CollectionSchemaMovableTableHOC.tsx | 33 +- .../views/collections/CollectionSchemaView.tsx | 2 +- .../views/collections/CollectionStackingView.tsx | 24 +- .../CollectionStackingViewFieldColumn.tsx | 8 +- src/client/views/collections/CollectionSubView.tsx | 31 +- .../views/collections/CollectionTreeView.tsx | 28 +- src/client/views/collections/CollectionView.tsx | 4 +- .../views/collections/CollectionViewChromes.tsx | 6 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 33 +- src/client/views/linking/LinkMenu.scss | 85 ----- src/client/views/linking/LinkMenuGroup.tsx | 28 +- src/client/views/linking/LinkMenuItem.scss | 87 +++++ src/client/views/linking/LinkMenuItem.tsx | 24 +- src/client/views/nodes/ButtonBox.tsx | 9 +- .../views/nodes/ContentFittingDocumentView.tsx | 7 +- src/client/views/nodes/DocuLinkBox.tsx | 4 +- src/client/views/nodes/DocumentView.tsx | 33 +- src/client/views/nodes/FieldView.tsx | 2 +- src/client/views/nodes/FormattedTextBox.tsx | 14 +- src/client/views/nodes/ImageBox.tsx | 10 +- src/client/views/pdf/PDFViewer.tsx | 12 +- src/client/views/search/SearchBox.tsx | 2 - src/client/views/search/SearchItem.tsx | 10 +- 37 files changed, 446 insertions(+), 571 deletions(-) create mode 100644 src/client/views/linking/LinkMenuItem.scss (limited to 'src/client/views/nodes/FieldView.tsx') diff --git a/src/client/northstar/dash-nodes/HistogramBox.tsx b/src/client/northstar/dash-nodes/HistogramBox.tsx index 854135648..8fee53fb9 100644 --- a/src/client/northstar/dash-nodes/HistogramBox.tsx +++ b/src/client/northstar/dash-nodes/HistogramBox.tsx @@ -46,8 +46,8 @@ export class HistogramBox extends React.Component { @action dropX = (e: Event, de: DragManager.DropEvent) => { - if (de.data instanceof DragManager.DocumentDragData) { - let h = Cast(de.data.draggedDocuments[0].data, HistogramField); + if (de.complete.docDragData) { + let h = Cast(de.complete.docDragData.draggedDocuments[0].data, HistogramField); if (h) { this.HistoOp.X = h.HistoOp.X; } @@ -57,8 +57,8 @@ export class HistogramBox extends React.Component { } @action dropY = (e: Event, de: DragManager.DropEvent) => { - if (de.data instanceof DragManager.DocumentDragData) { - let h = Cast(de.data.draggedDocuments[0].data, HistogramField); + if (de.complete.docDragData) { + let h = Cast(de.complete.docDragData.draggedDocuments[0].data, HistogramField); if (h) { this.HistoOp.Y = h.HistoOp.X; } @@ -78,10 +78,10 @@ export class HistogramBox extends React.Component { componentDidMount() { if (this._dropXRef.current) { - this._dropXDisposer = DragManager.MakeDropTarget(this._dropXRef.current, { handlers: { drop: this.dropX.bind(this) } }); + this._dropXDisposer = DragManager.MakeDropTarget(this._dropXRef.current, this.dropX.bind(this)); } if (this._dropYRef.current) { - this._dropYDisposer = DragManager.MakeDropTarget(this._dropYRef.current, { handlers: { drop: this.dropY.bind(this) } }); + this._dropYDisposer = DragManager.MakeDropTarget(this._dropYRef.current, this.dropY.bind(this)); } reaction(() => CurrentUserUtils.NorthstarDBCatalog, (catalog?: Catalog) => this.activateHistogramOperation(catalog), { fireImmediately: true }); reaction(() => [this.VisualBinRanges && this.VisualBinRanges.slice()], () => this.SizeConverter.SetVisualBinRanges(this.VisualBinRanges)); diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index 07247b7e9..6f65e6c68 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -108,7 +108,7 @@ export class DocumentManager { return init && rest; }) ).reduce((pairs, dv) => { - const linksList = LinkManager.Instance.getAllRelatedLinks(dv.props.Document); + const linksList = DocListCast(dv.props.Document.links); pairs.push(...linksList.reduce((pairs, link) => { const linkToDoc = link && LinkManager.Instance.getOppositeAnchor(link, dv.props.Document); linkToDoc && DocumentManager.Instance.getDocumentViews(linkToDoc).map(docView1 => { @@ -176,7 +176,7 @@ export class DocumentManager { } public async FollowLink(link: Doc | undefined, doc: Doc, focus: (doc: Doc, maxLocation: string) => void, zoom: boolean = false, reverse: boolean = false, currentContext?: Doc) { - const linkDocs = link ? [link] : LinkManager.Instance.getAllRelatedLinks(doc); + const linkDocs = link ? [link] : DocListCast(doc.links); SelectionManager.DeselectAll(); const firstDocs = linkDocs.filter(linkDoc => Doc.AreProtosEqual(linkDoc.anchor1 as Doc, doc)); const secondDocs = linkDocs.filter(linkDoc => Doc.AreProtosEqual(linkDoc.anchor2 as Doc, doc)); diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 9e6224d97..95529311a 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -1,5 +1,4 @@ -import { action, runInAction } from "mobx"; -import { Doc, Field } from "../../new_fields/Doc"; +import { Doc, Field, DocListCast } from "../../new_fields/Doc"; import { Cast, ScriptCast } from "../../new_fields/Types"; import { emptyFunction } from "../../Utils"; import { CollectionDockingView } from "../views/collections/CollectionDockingView"; @@ -22,7 +21,7 @@ export function SetupDrag( docFunc: () => Doc | Promise, moveFunc?: DragManager.MoveFunction, dropAction?: dropActionType, - options?: any, + treeViewId?: string, dontHideOnDrop?: boolean, dragStarted?: () => void ) { @@ -36,7 +35,7 @@ export function SetupDrag( const dragData = new DragManager.DocumentDragData([doc]); dragData.dropAction = dropAction; dragData.moveDocument = moveFunc; - dragData.options = options; + dragData.treeViewId = treeViewId; dragData.dontHideOnDrop = dontHideOnDrop; DragManager.StartDocumentDrag([_reference.current!], dragData, e.x, e.y); dragStarted && dragStarted(); @@ -65,62 +64,9 @@ export function SetupDrag( return onItemDown; } -function moveLinkedDocument(doc: Doc, targetCollection: Doc, addDocument: (doc: Doc) => boolean): boolean { - const document = SelectionManager.SelectedDocuments()[0]; - document && document.props.removeDocument && document.props.removeDocument(doc); - addDocument(doc); - return true; -} - -export async function DragLinkAsDocument(dragEle: HTMLElement, x: number, y: number, linkDoc: Doc, sourceDoc: Doc) { - const draggeddoc = LinkManager.Instance.getOppositeAnchor(linkDoc, sourceDoc); - if (draggeddoc) { - const moddrag = await Cast(draggeddoc.annotationOn, Doc); - const dragdocs = moddrag ? [moddrag] : [draggeddoc]; - const dragData = new DragManager.DocumentDragData(dragdocs); - dragData.moveDocument = moveLinkedDocument; - DragManager.StartLinkedDocumentDrag([dragEle], dragData, x, y, { - handlers: { - dragComplete: action(emptyFunction), - }, - hideSource: false - }); - } -} - -export async function DragLinksAsDocuments(dragEle: HTMLElement, x: number, y: number, sourceDoc: Doc, singleLink?: Doc) { - const srcTarg = sourceDoc.proto; - let draggedDocs: Doc[] = []; - - if (srcTarg) { - const linkDocs = singleLink ? [singleLink] : LinkManager.Instance.getAllRelatedLinks(srcTarg); - if (linkDocs) { - draggedDocs = linkDocs.map(link => { - const opp = LinkManager.Instance.getOppositeAnchor(link, sourceDoc); - if (opp) return opp; - }) as Doc[]; - } - } - if (draggedDocs.length) { - const moddrag: Doc[] = []; - for (const draggedDoc of draggedDocs) { - const doc = await Cast(draggedDoc.annotationOn, Doc); - if (doc) moddrag.push(doc); - } - const dragdocs = moddrag.length ? moddrag : draggedDocs; - const dragData = new DragManager.DocumentDragData(dragdocs); - dragData.moveDocument = moveLinkedDocument; - DragManager.StartLinkedDocumentDrag([dragEle], dragData, x, y, { - handlers: { - dragComplete: action(emptyFunction), - }, - hideSource: false - }); - } -} - - export namespace DragManager { + let dragDiv: HTMLDivElement; + export function Root() { const root = document.getElementById("root"); if (!root) { @@ -128,79 +74,45 @@ export namespace DragManager { } return root; } + export let AbortDrag: () => void = emptyFunction; + export type MoveFunction = (document: Doc, targetCollection: Doc | undefined, addDocument: (document: Doc) => boolean) => boolean; - let dragDiv: HTMLDivElement; - - export enum DragButtons { - Left = 1, - Right = 2, - Both = Left | Right - } - - interface DragOptions { - handlers: DragHandlers; - - hideSource: boolean | (() => boolean); - - dragHasStarted?: () => void; - - withoutShiftDrag?: boolean; - - finishDrag?: (dropData: { [id: string]: any }) => void; - - offsetX?: number; - + export interface DragDropDisposer { (): void; } + export interface DragOptions { + dragComplete?: (e: DragCompleteEvent) => void; // function to invoke when drag has completed + hideSource?: boolean; // hide source document during drag + offsetX?: number; // offset of top left of source drag visual from cursor offsetY?: number; } - export interface DragDropDisposer { - (): void; - } - - export class DragCompleteEvent { } - - export interface DragHandlers { - dragComplete: (e: DragCompleteEvent) => void; - } - - export interface DropOptions { - handlers: DropHandlers; - } + // event called when the drag operation results in a drop action export class DropEvent { constructor( readonly x: number, readonly y: number, - readonly data: { [id: string]: any }, - readonly mods: string + readonly complete: DragCompleteEvent, + readonly altKey: boolean, + readonly metaKey: boolean, + readonly ctrlKey: boolean ) { } } - export interface DropHandlers { - drop: (e: Event, de: DropEvent) => void; - } - - export function MakeDropTarget( - element: HTMLElement, - options: DropOptions - ): DragDropDisposer { - if ("canDrop" in element.dataset) { - throw new Error( - "Element is already droppable, can't make it droppable again" - ); + // event called when the drag operation has completed (aborted or completed a drop) -- this will be after any drop event has been generated + export class DragCompleteEvent { + constructor(aborted: boolean, dragData: { [id: string]: any }) { + this.aborted = aborted; + this.docDragData = dragData instanceof DocumentDragData ? dragData as DocumentDragData : undefined; + this.annoDragData = dragData instanceof PdfAnnoDragData ? dragData as PdfAnnoDragData : undefined; + this.linkDragData = dragData instanceof LinkDragData ? dragData as LinkDragData : undefined; + this.columnDragData = dragData instanceof ColumnDragData ? dragData as ColumnDragData : undefined; } - element.dataset.canDrop = "true"; - const handler = (e: Event) => { - const ce = e as CustomEvent; - options.handlers.drop(e, ce.detail); - }; - element.addEventListener("dashOnDrop", handler); - return () => { - element.removeEventListener("dashOnDrop", handler); - delete element.dataset.canDrop; - }; + aborted: boolean; + docDragData?: DocumentDragData; + annoDragData?: PdfAnnoDragData; + linkDragData?: LinkDragData; + columnDragData?: ColumnDragData; } - export type MoveFunction = (document: Doc, targetCollection: Doc, addDocument: (document: Doc) => boolean) => boolean; export class DocumentDragData { constructor(dragDoc: Doc[]) { this.draggedDocuments = dragDoc; @@ -210,6 +122,8 @@ export namespace DragManager { draggedDocuments: Doc[]; droppedDocuments: Doc[]; dragDivName?: string; + treeViewId?: string; + dontHideOnDrop?: boolean; offset: number[]; dropAction: dropActionType; userDropAction: dropActionType; @@ -217,16 +131,34 @@ export namespace DragManager { moveDocument?: MoveFunction; isSelectionMove?: boolean; // indicates that an explicitly selected Document is being dragged. this will suppress onDragStart scripts applyAsTemplate?: boolean; + } + export class LinkDragData { + constructor(linkSourceDoc: Doc) { + this.linkSourceDocument = linkSourceDoc; + } + droppedDocuments: Doc[] = []; + linkSourceDocument: Doc; + dontClearTextBox?: boolean; + linkDocument?: Doc; [id: string]: any; } - - export class AnnotationDragData { + export class ColumnDragData { + constructor(colKey: SchemaHeaderField) { + this.colKey = colKey; + } + colKey: SchemaHeaderField; + [id: string]: any; + } + // used by PDFs to conditionally (if the drop completes) create a text annotation when dragging from the PDF toolbar when a text region has been selected. + // this is pretty clunky and should be rethought out using linkDrag or DocumentDrag + export class PdfAnnoDragData { constructor(dragDoc: Doc, annotationDoc: Doc, dropDoc: Doc) { this.dragDocument = dragDoc; this.dropDocument = dropDoc; this.annotationDocument = annotationDoc; this.offset = [0, 0]; } + linkedToDoc?: boolean; targetContext: Doc | undefined; dragDocument: Doc; annotationDocument: Doc; @@ -236,98 +168,103 @@ export namespace DragManager { userDropAction: dropActionType; } - export let StartDragFunctions: (() => void)[] = []; + export function MakeDropTarget( + element: HTMLElement, + dropFunc: (e: Event, de: DropEvent) => void + ): DragDropDisposer { + if ("canDrop" in element.dataset) { + throw new Error( + "Element is already droppable, can't make it droppable again" + ); + } + element.dataset.canDrop = "true"; + const handler = (e: Event) => dropFunc(e, (e as CustomEvent).detail); + element.addEventListener("dashOnDrop", handler); + return () => { + element.removeEventListener("dashOnDrop", handler); + delete element.dataset.canDrop; + }; + } + // drag a document and drop it (or make an alias/copy on drop) export function StartDocumentDrag(eles: HTMLElement[], dragData: DocumentDragData, downX: number, downY: number, options?: DragOptions) { - runInAction(() => StartDragFunctions.map(func => func())); + const finishDrag = (e: DragCompleteEvent) => { + e.docDragData && (e.docDragData.droppedDocuments = + dragData.draggedDocuments.map(d => !dragData.isSelectionMove && !dragData.userDropAction && ScriptCast(d.onDragStart) ? ScriptCast(d.onDragStart).script.run({ this: d }).result : + dragData.userDropAction === "alias" || (!dragData.userDropAction && dragData.dropAction === "alias") ? Doc.MakeAlias(d) : + dragData.userDropAction === "copy" || (!dragData.userDropAction && dragData.dropAction === "copy") ? Doc.MakeCopy(d, true) : d) + ); + e.docDragData?.droppedDocuments.forEach((drop: Doc, i: number) => + Cast(dragData.draggedDocuments[i].removeDropProperties, listSpec("string"), []).map(prop => drop[prop] = undefined)); + }; dragData.draggedDocuments.map(d => d.dragFactory); // does this help? trying to make sure the dragFactory Doc is loaded - StartDrag(eles, dragData, downX, downY, options, options && options.finishDrag ? options.finishDrag : - (dropData: { [id: string]: any }) => { - (dropData.droppedDocuments = - dragData.draggedDocuments.map(d => !dragData.isSelectionMove && !dragData.userDropAction && ScriptCast(d.onDragStart) ? ScriptCast(d.onDragStart).script.run({ this: d }).result : - dragData.userDropAction === "alias" || (!dragData.userDropAction && dragData.dropAction === "alias") ? Doc.MakeAlias(d) : - dragData.userDropAction === "copy" || (!dragData.userDropAction && dragData.dropAction === "copy") ? Doc.MakeCopy(d, true) : d) - ); - dropData.droppedDocuments.forEach((drop: Doc, i: number) => - Cast(dragData.draggedDocuments[i].removeDropProperties, listSpec("string"), []).map(prop => drop[prop] = undefined)); - }); + StartDrag(eles, dragData, downX, downY, options, finishDrag); } + // drag a button template and drop a new button export function StartButtonDrag(eles: HTMLElement[], script: string, title: string, vars: { [name: string]: Field }, params: string[], initialize: (button: Doc) => void, downX: number, downY: number, options?: DragOptions) { - const dragData = new DragManager.DocumentDragData([]); - runInAction(() => StartDragFunctions.map(func => func())); - StartDrag(eles, dragData, downX, downY, options, options && options.finishDrag ? options.finishDrag : - (dropData: { [id: string]: any }) => { - const bd = Docs.Create.ButtonDocument({ width: 150, height: 50, title: title }); - bd.onClick = ScriptField.MakeScript(script); - params.map(p => Object.keys(vars).indexOf(p) !== -1 && (Doc.GetProto(bd)[p] = new PrefetchProxy(vars[p] as Doc))); - initialize && initialize(bd); - bd.buttonParams = new List(params); - dropData.droppedDocuments = [bd]; - }); + const finishDrag = (e: DragCompleteEvent) => { + const bd = Docs.Create.ButtonDocument({ width: 150, height: 50, title: title }); + bd.onClick = ScriptField.MakeScript(script); + params.map(p => Object.keys(vars).indexOf(p) !== -1 && (Doc.GetProto(bd)[p] = new PrefetchProxy(vars[p] as Doc))); + initialize && initialize(bd); + bd.buttonParams = new List(params); + e.docDragData && (e.docDragData.droppedDocuments = [bd]); + }; + StartDrag(eles, new DragManager.DocumentDragData([]), downX, downY, options, finishDrag); } - export function StartLinkedDocumentDrag(eles: HTMLElement[], dragData: DocumentDragData, downX: number, downY: number, options?: DragOptions) { - dragData.moveDocument = moveLinkedDocument; + // drag links and drop link targets (aliasing them if needed) + export async function StartLinkTargetsDrag(dragEle: HTMLElement, downX: number, downY: number, sourceDoc: Doc, specificLinks?: Doc[]) { + let draggedDocs = (specificLinks ? specificLinks : DocListCast(sourceDoc.links)).map(link => LinkManager.Instance.getOppositeAnchor(link, sourceDoc)).filter(l => l) as Doc[]; - runInAction(() => StartDragFunctions.map(func => func())); - StartDrag(eles, dragData, downX, downY, options, - (dropData: { [id: string]: any }) => { - const droppedDocuments: Doc[] = dragData.draggedDocuments.reduce((droppedDocs: Doc[], d) => { - const dvs = DocumentManager.Instance.getDocumentViews(d); - if (dvs.length) { - const containingView = SelectionManager.SelectedDocuments()[0] ? SelectionManager.SelectedDocuments()[0].props.ContainingCollectionView : undefined; - const inContext = dvs.filter(dv => dv.props.ContainingCollectionView === containingView); - if (inContext.length) { - inContext.forEach(dv => droppedDocs.push(dv.props.Document)); + if (draggedDocs.length) { + const moddrag: Doc[] = []; + for (const draggedDoc of draggedDocs) { + const doc = await Cast(draggedDoc.annotationOn, Doc); + if (doc) moddrag.push(doc); + } + + let dragData = new DragManager.DocumentDragData(moddrag.length ? moddrag : draggedDocs); + dragData.moveDocument = (doc: Doc, targetCollection: Doc | undefined, addDocument: (doc: Doc) => boolean): boolean => { + const document = SelectionManager.SelectedDocuments()[0]; + document && document.props.removeDocument && document.props.removeDocument(doc); + addDocument(doc); + return true; + }; + const containingView = SelectionManager.SelectedDocuments()[0] ? SelectionManager.SelectedDocuments()[0].props.ContainingCollectionView : undefined; + const finishDrag = (e: DragCompleteEvent) => + e.docDragData && (e.docDragData.droppedDocuments = + dragData.draggedDocuments.reduce((droppedDocs, d) => { + const dvs = DocumentManager.Instance.getDocumentViews(d).filter(dv => dv.props.ContainingCollectionView === containingView); + if (dvs.length) { + dvs.forEach(dv => droppedDocs.push(dv.props.Document)); } else { droppedDocs.push(Doc.MakeAlias(d)); } - } else { - droppedDocs.push(Doc.MakeAlias(d)); - } - return droppedDocs; - }, []); - dropData.droppedDocuments = droppedDocuments; - }); - } - - export function StartAnnotationDrag(eles: HTMLElement[], dragData: AnnotationDragData, downX: number, downY: number, options?: DragOptions) { - StartDrag(eles, dragData, downX, downY, options); - } + return droppedDocs; + }, [] as Doc[])); - export class LinkDragData { - constructor(linkSourceDoc: Doc, blacklist: Doc[] = []) { - this.linkSourceDocument = linkSourceDoc; - this.blacklist = blacklist; + StartDrag([dragEle], dragData, downX, downY, undefined, finishDrag); } - droppedDocuments: Doc[] = []; - linkSourceDocument: Doc; - blacklist: Doc[]; - dontClearTextBox?: boolean; - [id: string]: any; } - // for column dragging in schema view - export class ColumnDragData { - constructor(colKey: SchemaHeaderField) { - this.colKey = colKey; - } - colKey: SchemaHeaderField; - [id: string]: any; + // drag&drop the pdf annotation anchor which will create a text note on drop via a dropCompleted() DragOption + export function StartPdfAnnoDrag(eles: HTMLElement[], dragData: PdfAnnoDragData, downX: number, downY: number, options?: DragOptions) { + StartDrag(eles, dragData, downX, downY, options); } - export function StartLinkDrag(ele: HTMLElement, dragData: LinkDragData, downX: number, downY: number, options?: DragOptions) { - StartDrag([ele], dragData, downX, downY, options); + // drags a linker button and creates a link on drop + export function StartLinkDrag(ele: HTMLElement, sourceDoc: Doc, downX: number, downY: number, options?: DragOptions) { + StartDrag([ele], new DragManager.LinkDragData(sourceDoc), downX, downY, options); } + // drags a column from a schema view export function StartColumnDrag(ele: HTMLElement, dragData: ColumnDragData, downX: number, downY: number, options?: DragOptions) { StartDrag([ele], dragData, downX, downY, options); } - export let AbortDrag: () => void = emptyFunction; - - function StartDrag(eles: HTMLElement[], dragData: { [id: string]: any }, downX: number, downY: number, options?: DragOptions, finishDrag?: (dropData: { [id: string]: any }) => void) { + function StartDrag(eles: HTMLElement[], dragData: { [id: string]: any }, downX: number, downY: number, options?: DragOptions, finishDrag?: (dropData: DragCompleteEvent) => void) { eles = eles.filter(e => e); if (!dragDiv) { dragDiv = document.createElement("div"); @@ -341,33 +278,29 @@ export namespace DragManager { const xs: number[] = []; const ys: number[] = []; - const docs = dragData instanceof DocumentDragData ? dragData.draggedDocuments : - dragData instanceof AnnotationDragData ? [dragData.dragDocument] : []; + const docs = dragData instanceof DocumentDragData ? dragData.draggedDocuments : dragData instanceof PdfAnnoDragData ? [dragData.dragDocument] : []; const dragElements = eles.map(ele => { - const w = ele.offsetWidth, - h = ele.offsetHeight; + if (!ele.parentNode) dragDiv.appendChild(ele); + const dragElement = ele.parentNode === dragDiv ? ele : ele.cloneNode(true) as HTMLElement; const rect = ele.getBoundingClientRect(); - const scaleX = rect.width / w, - scaleY = rect.height / h; - const x = rect.left, - y = rect.top; - xs.push(x); - ys.push(y); + const scaleX = rect.width / ele.offsetWidth, + scaleY = rect.height / ele.offsetHeight; + xs.push(rect.left); + ys.push(rect.top); scaleXs.push(scaleX); scaleYs.push(scaleY); - const dragElement = ele.cloneNode(true) as HTMLElement; dragElement.style.opacity = "0.7"; - dragElement.style.borderRadius = getComputedStyle(ele).borderRadius; dragElement.style.position = "absolute"; dragElement.style.margin = "0"; dragElement.style.top = "0"; dragElement.style.bottom = ""; dragElement.style.left = "0"; - dragElement.style.transition = "none"; dragElement.style.color = "black"; + dragElement.style.transition = "none"; dragElement.style.transformOrigin = "0 0"; + dragElement.style.borderRadius = getComputedStyle(ele).borderRadius; dragElement.style.zIndex = globalCssVariables.contextMenuZindex;// "1000"; - dragElement.style.transform = `translate(${x + (options?.offsetX || 0)}px, ${y + (options?.offsetY || 0)}px) scale(${scaleX}, ${scaleY})`; + dragElement.style.transform = `translate(${rect.left + (options?.offsetX || 0)}px, ${rect.top + (options?.offsetY || 0)}px) scale(${scaleX}, ${scaleY})`; dragElement.style.width = `${rect.width / scaleX}px`; dragElement.style.height = `${rect.height / scaleY}px`; @@ -385,30 +318,18 @@ export namespace DragManager { Array.from(pdfView).map((v, i) => v.scrollTo({ top: tops[i] })); }, 0); } - const set = dragElement.getElementsByTagName('*'); if (dragElement.hasAttribute("style")) (dragElement as any).style.pointerEvents = "none"; + const set = dragElement.getElementsByTagName('*'); // tslint:disable-next-line: prefer-for-of for (let i = 0; i < set.length; i++) { - if (set[i].hasAttribute("style")) { - const s = set[i]; - (s as any).style.pointerEvents = "none"; - } + set[i].hasAttribute("style") && ((set[i] as any).style.pointerEvents = "none"); } - dragDiv.appendChild(dragElement); return dragElement; }); - let hideSource = false; - if (options) { - if (typeof options.hideSource === "boolean") { - hideSource = options.hideSource; - } else { - hideSource = options.hideSource(); - } - } - + const hideSource = options?.hideSource ? true : false; eles.map(ele => ele.parentElement && ele.parentElement?.className === dragData.dragDivName ? (ele.parentElement.hidden = hideSource) : (ele.hidden = hideSource)); let lastX = downX; @@ -418,9 +339,9 @@ export namespace DragManager { if (dragData instanceof DocumentDragData) { dragData.userDropAction = e.ctrlKey ? "alias" : undefined; } - if (((options && !options.withoutShiftDrag) || !options) && e.shiftKey && CollectionDockingView.Instance) { + if (e.shiftKey && CollectionDockingView.Instance) { AbortDrag(); - finishDrag && finishDrag(dragData); + finishDrag?.(new DragCompleteEvent(true, dragData)); CollectionDockingView.Instance.StartOtherDrag({ pageX: e.pageX, pageY: e.pageY, @@ -445,45 +366,40 @@ export namespace DragManager { const endDrag = () => { document.removeEventListener("pointermove", moveHandler, true); document.removeEventListener("pointerup", upHandler); - if (options) { - options.handlers.dragComplete({}); - } }; AbortDrag = () => { hideDragShowOriginalElements(); SelectionManager.SetIsDragging(false); + options?.dragComplete?.(new DragCompleteEvent(true, dragData)); endDrag(); }; const upHandler = (e: PointerEvent) => { hideDragShowOriginalElements(); dispatchDrag(eles, e, dragData, options, finishDrag); SelectionManager.SetIsDragging(false); + options?.dragComplete?.(new DragCompleteEvent(false, dragData)); endDrag(); }; document.addEventListener("pointermove", moveHandler, true); document.addEventListener("pointerup", upHandler); } - function dispatchDrag(dragEles: HTMLElement[], e: PointerEvent, dragData: { [index: string]: any }, options?: DragOptions, finishDrag?: (dragData: { [index: string]: any }) => void) { + function dispatchDrag(dragEles: HTMLElement[], e: PointerEvent, dragData: { [index: string]: any }, options?: DragOptions, finishDrag?: (e: DragCompleteEvent) => void) { const removed = dragData.dontHideOnDrop ? [] : dragEles.map(dragEle => { - // let parent = dragEle.parentElement; - // if (parent) parent.removeChild(dragEle); - const ret = [dragEle, dragEle.style.width, dragEle.style.height]; + const ret = { ele: dragEle, w: dragEle.style.width, h: dragEle.style.height }; dragEle.style.width = "0"; dragEle.style.height = "0"; return ret; }); const target = document.elementFromPoint(e.x, e.y); removed.map(r => { - const dragEle = r[0] as HTMLElement; - dragEle.style.width = r[1] as string; - dragEle.style.height = r[2] as string; - // let parent = r[1]; - // if (parent && dragEle) parent.appendChild(dragEle); + r.ele.style.width = r.w; + r.ele.style.height = r.h; }); if (target) { - finishDrag && finishDrag(dragData); + const complete = new DragCompleteEvent(false, dragData); + finishDrag?.(complete); target.dispatchEvent( new CustomEvent("dashOnDrop", { @@ -491,8 +407,10 @@ export namespace DragManager { detail: { x: e.x, y: e.y, - data: dragData, - mods: e.altKey ? "AltKey" : e.ctrlKey ? "CtrlKey" : e.metaKey ? "MetaKey" : "" + complete: complete, + altKey: e.altKey, + metaKey: e.metaKey, + ctrlKey: e.ctrlKey } }) ); diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts index fb6f27478..5f3667acc 100644 --- a/src/client/util/LinkManager.ts +++ b/src/client/util/LinkManager.ts @@ -70,7 +70,7 @@ export class LinkManager { } // finds all links that contain the given anchor - public getAllRelatedLinks(anchor: Doc): Doc[] {//List { + public getAllRelatedLinks(anchor: Doc): Doc[] { const related = LinkManager.Instance.getAllLinks().filter(link => { const protomatch1 = Doc.AreProtosEqual(anchor, Cast(link.anchor1, Doc, null)); const protomatch2 = Doc.AreProtosEqual(anchor, Cast(link.anchor2, Doc, null)); @@ -244,7 +244,5 @@ export class LinkManager { if (Doc.AreProtosEqual(anchor, linkDoc)) return linkDoc; } } -Scripting.addGlobal(function links(doc: any) { - return new List(LinkManager.Instance.getAllRelatedLinks(doc)); -}); +Scripting.addGlobal(function links(doc: any) { return new List(LinkManager.Instance.getAllRelatedLinks(doc)); }); \ No newline at end of file diff --git a/src/client/views/CollectionLinearView.tsx b/src/client/views/CollectionLinearView.tsx index 293a4feea..5ca861f71 100644 --- a/src/client/views/CollectionLinearView.tsx +++ b/src/client/views/CollectionLinearView.tsx @@ -39,7 +39,7 @@ export class CollectionLinearView extends CollectionSubView(LinearDocument) { protected createDropTarget = (ele: HTMLDivElement) => { //used for stacking and masonry view this._dropDisposer && this._dropDisposer(); if (ele) { - this._dropDisposer = DragManager.MakeDropTarget(ele, { handlers: { drop: this.drop.bind(this) } }); + this._dropDisposer = DragManager.MakeDropTarget(ele, this.drop.bind(this)); } } diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx index 27ee9f122..c7ddee7ea 100644 --- a/src/client/views/DocComponent.tsx +++ b/src/client/views/DocComponent.tsx @@ -71,7 +71,7 @@ export function DocAnnotatableComponent

(schema // if the moved document is already in this overlay collection nothing needs to be done. // otherwise, if the document can be removed from where it was, it will then be added to this document's overlay collection. @action.bound - moveDocument(doc: Doc, targetCollection: Doc, addDocument: (doc: Doc) => boolean): boolean { + moveDocument(doc: Doc, targetCollection: Doc | undefined, addDocument: (doc: Doc) => boolean): boolean { return Doc.AreProtosEqual(this.props.Document, targetCollection) ? true : this.removeDocument(doc) ? addDocument(doc) : false; } @action.bound diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx index 7f125dd34..f014c1329 100644 --- a/src/client/views/DocumentButtonBar.tsx +++ b/src/client/views/DocumentButtonBar.tsx @@ -3,13 +3,12 @@ import { faArrowAltCircleDown, faArrowAltCircleUp, faCheckCircle, faCloudUploadA import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { action, observable, runInAction, computed } from "mobx"; import { observer } from "mobx-react"; -import { Doc } from "../../new_fields/Doc"; +import { Doc, DocListCast } from "../../new_fields/Doc"; import { RichTextField } from '../../new_fields/RichTextField'; -import { NumCast, StrCast } from "../../new_fields/Types"; +import { NumCast, StrCast, Cast } from "../../new_fields/Types"; import { emptyFunction } from "../../Utils"; import { Pulls, Pushes } from '../apis/google_docs/GoogleApiClientUtils'; import { DragManager } from "../util/DragManager"; -import { LinkManager } from '../util/LinkManager'; import { UndoManager } from "../util/UndoManager"; import './DocumentButtonBar.scss'; import './collections/ParentDocumentSelector.scss'; @@ -107,27 +106,21 @@ export class DocumentButtonBar extends React.Component<{ views: DocumentView[], if (this._linkButton.current !== null && (Math.abs(e.clientX - this._downX) > 3 || Math.abs(e.clientY - this._downY) > 3)) { document.removeEventListener("pointermove", this.onLinkButtonMoved); document.removeEventListener("pointerup", this.onLinkButtonUp); - const docView = this.props.views[0]; - const container = docView.props.ContainingCollectionDoc?.proto; - const dragData = new DragManager.LinkDragData(docView.props.Document, container ? [container] : []); const linkDrag = UndoManager.StartBatch("Drag Link"); - DragManager.StartLinkDrag(this._linkButton.current, dragData, e.pageX, e.pageY, { - handlers: { - dragComplete: () => { - const tooltipmenu = FormattedTextBox.ToolTipTextMenu; - const linkDoc = dragData.linkDocument; - if (linkDoc && tooltipmenu) { - const proto = Doc.GetProto(linkDoc); - if (proto && docView) { - proto.sourceContext = docView.props.ContainingCollectionDoc; - } - const text = tooltipmenu.makeLink(linkDoc, StrCast(linkDoc.anchor2.title), e.ctrlKey ? "onRight" : "inTab"); - if (linkDoc instanceof Doc && linkDoc.anchor2 instanceof Doc) { - proto.title = text === "" ? proto.title : text + " to " + linkDoc.anchor2.title; // TODODO open to more descriptive descriptions of following in text link - } + DragManager.StartLinkDrag(this._linkButton.current, this.props.views[0].props.Document, e.pageX, e.pageY, { + dragComplete: dropEv => { + const linkDoc = dropEv.linkDragData?.linkDocument; // equivalent to !dropEve.aborted since linkDocument is only assigned on a completed drop + if (linkDoc && FormattedTextBox.ToolTipTextMenu) { + const proto = Doc.GetProto(linkDoc); + proto.sourceContext = this.props.views[0].props.ContainingCollectionDoc; + + const anchor2Title = linkDoc.anchor2 instanceof Doc ? StrCast((linkDoc.anchor2 as Doc).title) : "-untitled-"; + const text = FormattedTextBox.ToolTipTextMenu.makeLink(linkDoc, anchor2Title, e.ctrlKey ? "onRight" : "inTab"); + if (linkDoc.anchor2 instanceof Doc) { + proto.title = text === "" ? proto.title : text + " to " + linkDoc.anchor2.title; // TODO open to more descriptive descriptions of following in text link } - linkDrag && linkDrag.end(); } + linkDrag?.end(); }, hideSource: false }); @@ -200,7 +193,7 @@ export class DocumentButtonBar extends React.Component<{ views: DocumentView[], @computed get linkButton() { - const linkCount = LinkManager.Instance.getAllRelatedLinks(this.props.views[0].props.Document).length; + const linkCount = DocListCast(this.props.views[0].props.Document.links).length; return

}> diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index f366a3677..fdaca87a9 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -199,7 +199,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> document.removeEventListener("pointermove", this.onTitleMove); document.removeEventListener("pointerup", this.onTitleUp); DragManager.StartDocumentDrag(SelectionManager.SelectedDocuments().map(documentView => documentView.ContentDiv!), dragData, e.x, e.y, { - handlers: { dragComplete: action(() => this._hidden = this.Interacting = false) }, + dragComplete: action(e => this._hidden = this.Interacting = false), hideSource: true }); e.stopPropagation(); diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 25b7dc5ec..db2a3c298 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -460,7 +460,7 @@ export class MainView extends React.Component { addButtonDoc = (doc: Doc) => Doc.AddDocToList(CurrentUserUtils.UserDocument.expandingButtons as Doc, "data", doc); remButtonDoc = (doc: Doc) => Doc.RemoveDocFromList(CurrentUserUtils.UserDocument.expandingButtons as Doc, "data", doc); - moveButtonDoc = (doc: Doc, targetCollection: Doc, addDocument: (document: Doc) => boolean) => this.remButtonDoc(doc) && addDocument(doc); + moveButtonDoc = (doc: Doc, targetCollection: Doc | undefined, addDocument: (document: Doc) => boolean) => this.remButtonDoc(doc) && addDocument(doc); buttonBarXf = () => { if (!this._docBtnRef.current) return Transform.Identity(); diff --git a/src/client/views/OverlayView.tsx b/src/client/views/OverlayView.tsx index cd330d492..350a75d29 100644 --- a/src/client/views/OverlayView.tsx +++ b/src/client/views/OverlayView.tsx @@ -9,8 +9,6 @@ import { DocListCast, Doc } from "../../new_fields/Doc"; import { Id } from "../../new_fields/FieldSymbols"; import { DocumentView } from "./nodes/DocumentView"; import { Transform } from "../util/Transform"; -import { CollectionFreeFormDocumentView } from "./nodes/CollectionFreeFormDocumentView"; -import { DocumentContentsView } from "./nodes/DocumentContentsView"; import { NumCast } from "../../new_fields/Types"; import { CollectionFreeFormLinksView } from "./collections/collectionFreeForm/CollectionFreeFormLinksView"; diff --git a/src/client/views/TemplateMenu.tsx b/src/client/views/TemplateMenu.tsx index 8d9dc4cf7..f7cfc4022 100644 --- a/src/client/views/TemplateMenu.tsx +++ b/src/client/views/TemplateMenu.tsx @@ -66,7 +66,7 @@ export class TemplateMenu extends React.Component { const ex = e.target.getBoundingClientRect().left; const ey = e.target.getBoundingClientRect().top; const de = new DragManager.DocumentDragData([topDoc]); - de.dragDivName = topDocView.props.dragDivName; + de.dragDivName = topDocView.props.dragDivName; de.moveDocument = topDocView.props.moveDocument; undoBatch(action(() => topDoc.z = topDoc.z ? 0 : 1))(); setTimeout(() => { @@ -74,11 +74,7 @@ export class TemplateMenu extends React.Component { if (newDocView) { const contentDiv = newDocView.ContentDiv!; const xf = contentDiv.getBoundingClientRect(); - DragManager.StartDocumentDrag([contentDiv], de, ex, ey, { - offsetX: ex - xf.left, offsetY: ey - xf.top, - handlers: { dragComplete: () => { }, }, - hideSource: true - }); + DragManager.StartDocumentDrag([contentDiv], de, ex, ey, { offsetX: ex - xf.left, offsetY: ey - xf.top, hideSource: true }); } }, 0); } @@ -148,9 +144,6 @@ export class TemplateMenu extends React.Component { DragManager.StartDocumentDrag([dragDocView.ContentDiv!], dragData, left, top, { offsetX: dragData.offset[0], offsetY: dragData.offset[1], - handlers: { - dragComplete: action(emptyFunction), - }, hideSource: false }); } diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index ffcb3e9ce..08b9fd216 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -20,7 +20,7 @@ import { emptyFunction, returnEmptyString, returnFalse, returnOne, returnTrue, U import { DocServer } from "../../DocServer"; import { Docs } from '../../documents/Documents'; import { DocumentManager } from '../../util/DocumentManager'; -import { DragLinksAsDocuments, DragManager } from "../../util/DragManager"; +import { DragManager } from "../../util/DragManager"; import { SelectionManager } from '../../util/SelectionManager'; import { Transform } from '../../util/Transform'; import { undoBatch } from "../../util/UndoManager"; @@ -346,7 +346,7 @@ export class CollectionDockingView extends React.Component) => - (sourceDoc instanceof Doc) && DragLinksAsDocuments(tab, x, y, sourceDoc))); + (sourceDoc instanceof Doc) && DragManager.StartLinkTargetsDrag(tab, x, y, sourceDoc))); } if (className === "lm_drag_handle" || className === "lm_close" || className === "lm_maximise" || className === "lm_minimise" || className === "lm_close_tab") { this._flush = true; @@ -419,15 +419,13 @@ export class CollectionDockingView extends React.Component { - e.preventDefault(); - e.stopPropagation(); - DragManager.StartDocumentDrag([dragSpan], new DragManager.DocumentDragData([doc]), e.clientX, e.clientY, { - handlers: { dragComplete: emptyFunction }, - hideSource: false - }); - }}>, dragSpan); + onPointerDown={e => { + e.preventDefault(); + e.stopPropagation(); + DragManager.StartDocumentDrag([dragSpan], new DragManager.DocumentDragData([doc]), e.clientX, e.clientY); + }}> + + , dragSpan); ReactDOM.render(, gearSpan); tab.reactComponents = [dragSpan, gearSpan, upDiv]; tab.element.append(dragSpan); diff --git a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx index d697e721b..80752303c 100644 --- a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx +++ b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx @@ -56,7 +56,7 @@ export class CollectionMasonryViewFieldRow extends React.Component { this._dropDisposer && this._dropDisposer(); if (ele) { - this._dropDisposer = DragManager.MakeDropTarget(ele, { handlers: { drop: this.rowDrop.bind(this) } }); + this._dropDisposer = DragManager.MakeDropTarget(ele, this.rowDrop.bind(this)); } } @@ -74,12 +74,12 @@ export class CollectionMasonryViewFieldRow extends React.Component { this._createAliasSelected = false; - if (de.data instanceof DragManager.DocumentDragData) { + if (de.complete.docDragData) { (this.props.parent.Document.dropConverter instanceof ScriptField) && - this.props.parent.Document.dropConverter.script.run({ dragData: de.data }); + this.props.parent.Document.dropConverter.script.run({ dragData: de.complete.docDragData }); const key = StrCast(this.props.parent.props.Document.sectionFilter); const castedValue = this.getValue(this._heading); - de.data.droppedDocuments.forEach(d => d[key] = castedValue); + de.complete.docDragData.droppedDocuments.forEach(d => d[key] = castedValue); this.props.parent.drop(e, de); e.stopPropagation(); } @@ -171,10 +171,8 @@ export class CollectionMasonryViewFieldRow extends React.Component boolean; pinToPres: (document: Doc) => void; - moveDocument: (document: Doc, targetCollection: Doc, addDocument: (document: Doc) => boolean) => boolean; + moveDocument: (document: Doc, targetCollection: Doc | undefined, addDocument: (document: Doc) => boolean) => boolean; isFocused: boolean; changeFocusedCellByIndex: (row: number, col: number) => void; setIsEditing: (isEditing: boolean) => void; @@ -105,13 +105,13 @@ export class CollectionSchemaCell extends React.Component { } private drop = (e: Event, de: DragManager.DropEvent) => { - if (de.data instanceof DragManager.DocumentDragData) { + if (de.complete.docDragData) { const fieldKey = this.props.rowProps.column.id as string; - if (de.data.draggedDocuments.length === 1) { - this._document[fieldKey] = de.data.draggedDocuments[0]; + if (de.complete.docDragData.draggedDocuments.length === 1) { + this._document[fieldKey] = de.complete.docDragData.draggedDocuments[0]; } else { - const coll = Docs.Create.SchemaDocument([new SchemaHeaderField("title", "#f1efeb")], de.data.draggedDocuments, {}); + const coll = Docs.Create.SchemaDocument([new SchemaHeaderField("title", "#f1efeb")], de.complete.docDragData.draggedDocuments, {}); this._document[fieldKey] = coll; } e.stopPropagation(); @@ -121,7 +121,7 @@ export class CollectionSchemaCell extends React.Component { private dropRef = (ele: HTMLElement | null) => { this._dropDisposer && this._dropDisposer(); if (ele) { - this._dropDisposer = DragManager.MakeDropTarget(ele, { handlers: { drop: this.drop.bind(this) } }); + this._dropDisposer = DragManager.MakeDropTarget(ele, this.drop.bind(this)); } } @@ -167,11 +167,10 @@ export class CollectionSchemaCell extends React.Component { const fieldIsDoc = (type === "document" && typeof field === "object") || (typeof field === "object" && doc); const onItemDown = (e: React.PointerEvent) => { - if (fieldIsDoc) { - SetupDrag(this._focusRef, () => this._document[props.fieldKey] instanceof Doc ? this._document[props.fieldKey] : this._document, - this._document[props.fieldKey] instanceof Doc ? (doc: Doc, target: Doc, addDoc: (newDoc: Doc) => any) => addDoc(doc) : this.props.moveDocument, - this._document[props.fieldKey] instanceof Doc ? "alias" : this.props.Document.schemaDoc ? "copy" : undefined)(e); - } + fieldIsDoc && SetupDrag(this._focusRef, + () => this._document[props.fieldKey] instanceof Doc ? this._document[props.fieldKey] : this._document, + this._document[props.fieldKey] instanceof Doc ? (doc: Doc, target: Doc | undefined, addDoc: (newDoc: Doc) => any) => addDoc(doc) : this.props.moveDocument, + this._document[props.fieldKey] instanceof Doc ? "alias" : this.props.Document.schemaDoc ? "copy" : undefined)(e); }; const onPointerEnter = (e: React.PointerEvent): void => { if (e.buttons === 1 && SelectionManager.GetIsDragging() && (type === "document" || type === undefined)) { diff --git a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx index 90320df82..153bbd410 100644 --- a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx +++ b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx @@ -56,7 +56,7 @@ export class MovableColumn extends React.Component { createColDropTarget = (ele: HTMLDivElement) => { this._colDropDisposer && this._colDropDisposer(); if (ele) { - this._colDropDisposer = DragManager.MakeDropTarget(ele, { handlers: { drop: this.colDrop.bind(this) } }); + this._colDropDisposer = DragManager.MakeDropTarget(ele, this.colDrop.bind(this)); } } @@ -66,8 +66,8 @@ export class MovableColumn extends React.Component { const rect = this._header!.current!.getBoundingClientRect(); const bounds = this.props.ScreenToLocalTransform().transformPoint(rect.left + ((rect.right - rect.left) / 2), rect.top); const before = x[0] < bounds[0]; - if (de.data instanceof DragManager.ColumnDragData) { - this.props.reorderColumns(de.data.colKey, this.props.columnValue, before, this.props.allColumns); + if (de.complete.columnDragData) { + this.props.reorderColumns(de.complete.columnDragData.colKey, this.props.columnValue, before, this.props.allColumns); return true; } return false; @@ -165,7 +165,7 @@ export class MovableRow extends React.Component { createRowDropTarget = (ele: HTMLDivElement) => { this._rowDropDisposer && this._rowDropDisposer(); if (ele) { - this._rowDropDisposer = DragManager.MakeDropTarget(ele, { handlers: { drop: this.rowDrop.bind(this) } }); + this._rowDropDisposer = DragManager.MakeDropTarget(ele, this.rowDrop.bind(this)); } } @@ -178,16 +178,17 @@ export class MovableRow extends React.Component { const bounds = this.props.ScreenToLocalTransform().transformPoint(rect.left, rect.top + rect.height / 2); const before = x[1] < bounds[1]; - if (de.data instanceof DragManager.DocumentDragData) { + const docDragData = de.complete.docDragData; + if (docDragData) { e.stopPropagation(); - if (de.data.draggedDocuments[0] === rowDoc) return true; + if (docDragData.draggedDocuments[0] === rowDoc) return true; const addDocument = (doc: Doc) => this.props.addDoc(doc, rowDoc, before); - const movedDocs = de.data.draggedDocuments; - return (de.data.dropAction || de.data.userDropAction) ? - de.data.droppedDocuments.reduce((added: boolean, d) => this.props.addDoc(d, rowDoc, before) || added, false) - : (de.data.moveDocument) ? - movedDocs.reduce((added: boolean, d) => de.data.moveDocument(d, rowDoc, addDocument) || added, false) - : de.data.droppedDocuments.reduce((added: boolean, d) => this.props.addDoc(d, rowDoc, before), false); + const movedDocs = docDragData.draggedDocuments; + return (docDragData.dropAction || docDragData.userDropAction) ? + docDragData.droppedDocuments.reduce((added: boolean, d) => this.props.addDoc(d, rowDoc, before) || added, false) + : (docDragData.moveDocument) ? + movedDocs.reduce((added: boolean, d) => docDragData.moveDocument?.(d, rowDoc, addDocument) || added, false) + : docDragData.droppedDocuments.reduce((added: boolean, d) => this.props.addDoc(d, rowDoc, before), false); } return false; } @@ -199,12 +200,12 @@ export class MovableRow extends React.Component { @undoBatch @action - move: DragManager.MoveFunction = (doc: Doc, target: Doc, addDoc) => { - const targetView = DocumentManager.Instance.getDocumentView(target); + move: DragManager.MoveFunction = (doc: Doc, targetCollection: Doc | undefined, addDoc) => { + const targetView = targetCollection && DocumentManager.Instance.getDocumentView(targetCollection); if (targetView && targetView.props.ContainingCollectionDoc) { - return doc !== target && doc !== targetView.props.ContainingCollectionDoc && this.props.removeDoc(doc) && addDoc(doc); + return doc !== targetCollection && doc !== targetView.props.ContainingCollectionDoc && this.props.removeDoc(doc) && addDoc(doc); } - return doc !== target && this.props.removeDoc(doc) && addDoc(doc); + return doc !== targetCollection && this.props.removeDoc(doc) && addDoc(doc); } render() { diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index 8169e9e2b..bb706e528 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -224,7 +224,7 @@ export interface SchemaTableProps { renderDepth: number; deleteDocument: (document: Doc) => boolean; addDocument: (document: Doc) => boolean; - moveDocument: (document: Doc, targetCollection: Doc, addDocument: (document: Doc) => boolean) => boolean; + moveDocument: (document: Doc, targetCollection: Doc | undefined, addDocument: (document: Doc) => boolean) => boolean; ScreenToLocalTransform: () => Transform; active: (outsideReaction: boolean) => boolean; onDrop: (e: React.DragEvent, options: DocumentOptions, completed?: (() => void) | undefined) => void; diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index ff3417b77..6a23920f3 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -147,7 +147,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { } @action - moveDocument = (doc: Doc, targetCollection: Doc, addDocument: (document: Doc) => boolean): boolean => { + moveDocument = (doc: Doc, targetCollection: Doc | undefined, addDocument: (document: Doc) => boolean): boolean => { return this.props.removeDocument(doc) && addDocument(doc); } createRef = (ele: HTMLDivElement | null) => { @@ -243,7 +243,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { const where = [de.x, de.y]; let targInd = -1; let plusOne = false; - if (de.data instanceof DragManager.DocumentDragData) { + if (de.complete.docDragData) { this._docXfs.map((cd, i) => { const pos = cd.dxf().inverse().transformPoint(-2 * this.gridGap, -2 * this.gridGap); const pos1 = cd.dxf().inverse().transformPoint(cd.width(), cd.height()); @@ -252,16 +252,16 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { plusOne = (where[1] > (pos[1] + pos1[1]) / 2 ? 1 : 0) ? true : false; } }); - } - if (super.drop(e, de)) { - const newDoc = de.data.droppedDocuments[0]; - const docs = this.childDocList; - if (docs) { - if (targInd === -1) targInd = docs.length; - else targInd = docs.indexOf(this.filteredChildren[targInd]); - const srcInd = docs.indexOf(newDoc); - docs.splice(srcInd, 1); - docs.splice((targInd > srcInd ? targInd - 1 : targInd) + (plusOne ? 1 : 0), 0, newDoc); + if (super.drop(e, de)) { + const newDoc = de.complete.docDragData.droppedDocuments[0]; + const docs = this.childDocList; + if (docs) { + if (targInd === -1) targInd = docs.length; + else targInd = docs.indexOf(this.filteredChildren[targInd]); + const srcInd = docs.indexOf(newDoc); + docs.splice(srcInd, 1); + docs.splice((targInd > srcInd ? targInd - 1 : targInd) + (plusOne ? 1 : 0), 0, newDoc); + } } } return false; diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx index ca3b93bf8..39b4e4e1d 100644 --- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx +++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx @@ -51,21 +51,21 @@ export class CollectionStackingViewFieldColumn extends React.Component { this._createAliasSelected = false; - if (de.data instanceof DragManager.DocumentDragData) { + if (de.complete.docDragData) { const key = StrCast(this.props.parent.props.Document.sectionFilter); const castedValue = this.getValue(this._heading); if (castedValue) { - de.data.droppedDocuments.forEach(d => d[key] = castedValue); + de.complete.docDragData.droppedDocuments.forEach(d => d[key] = castedValue); } else { - de.data.droppedDocuments.forEach(d => d[key] = undefined); + de.complete.docDragData.droppedDocuments.forEach(d => d[key] = undefined); } this.props.parent.drop(e, de); e.stopPropagation(); diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 9fa244546..5c7794cc0 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -27,7 +27,7 @@ import { Networking } from "../../Network"; export interface CollectionViewProps extends FieldViewProps { addDocument: (document: Doc) => boolean; removeDocument: (document: Doc) => boolean; - moveDocument: (document: Doc, targetCollection: Doc, addDocument: (document: Doc) => boolean) => boolean; + moveDocument: (document: Doc, targetCollection: Doc | undefined, addDocument: (document: Doc) => boolean) => boolean; PanelWidth: () => number; PanelHeight: () => number; VisibleHeight?: () => number; @@ -51,7 +51,7 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T) { protected createDropTarget = (ele: HTMLDivElement) => { //used for stacking and masonry view this.dropDisposer && this.dropDisposer(); if (ele) { - this.dropDisposer = DragManager.MakeDropTarget(ele, { handlers: { drop: this.drop.bind(this) } }); + this.dropDisposer = DragManager.MakeDropTarget(ele, this.drop.bind(this)); } } protected CreateDropTarget(ele: HTMLDivElement) { //used in schema view @@ -132,32 +132,33 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T) { @undoBatch @action protected drop(e: Event, de: DragManager.DropEvent): boolean { + const docDragData = de.complete.docDragData; (this.props.Document.dropConverter instanceof ScriptField) && - this.props.Document.dropConverter.script.run({ dragData: de.data }); - if (de.data instanceof DragManager.DocumentDragData && !de.data.applyAsTemplate) { - if (de.mods === "AltKey" && de.data.draggedDocuments.length) { + 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(de.data.draggedDocuments[0], doc, "layoutFromParent")); + Doc.ApplyTemplateTo(docDragData.draggedDocuments[0], doc, "layoutFromParent")); e.stopPropagation(); return true; } let added = false; - if (de.data.dropAction || de.data.userDropAction) { - added = de.data.droppedDocuments.reduce((added: boolean, d) => this.props.addDocument(d) || added, false); - } else if (de.data.moveDocument) { - const movedDocs = de.data.draggedDocuments; + if (docDragData.dropAction || docDragData.userDropAction) { + added = docDragData.droppedDocuments.reduce((added: boolean, d) => this.props.addDocument(d) || added, false); + } else if (docDragData.moveDocument) { + const movedDocs = docDragData.draggedDocuments; added = movedDocs.reduce((added: boolean, d, i) => - de.data.droppedDocuments[i] !== d ? this.props.addDocument(de.data.droppedDocuments[i]) : - de.data.moveDocument(d, this.props.Document, this.props.addDocument) || added, false); + docDragData.droppedDocuments[i] !== d ? this.props.addDocument(docDragData.droppedDocuments[i]) : + docDragData.moveDocument?.(d, this.props.Document, this.props.addDocument) || added, false); } else { - added = de.data.droppedDocuments.reduce((added: boolean, d) => this.props.addDocument(d) || added, false); + added = docDragData.droppedDocuments.reduce((added: boolean, d) => this.props.addDocument(d) || added, false); } e.stopPropagation(); return added; } - else if (de.data instanceof DragManager.AnnotationDragData) { + else if (de.complete.annoDragData) { e.stopPropagation(); - return this.props.addDocument(de.data.dropDocument); + return this.props.addDocument(de.complete.annoDragData.dropDocument); } return false; } diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index ec1e7409f..0a22a897c 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -123,7 +123,7 @@ class TreeView extends React.Component { @undoBatch delete = () => this.props.deleteDoc(this.props.document); @undoBatch openRight = () => this.props.addDocTab(this.props.document, this.templateDataDoc, "onRight", this.props.libraryPath); @undoBatch indent = () => this.props.addDocument(this.props.document) && this.delete(); - @undoBatch move = (doc: Doc, target: Doc, addDoc: (doc: Doc) => boolean) => { + @undoBatch move = (doc: Doc, target: Doc | undefined, addDoc: (doc: Doc) => boolean) => { return this.props.document !== target && this.props.deleteDoc(doc) && addDoc(doc); } @undoBatch @action remove = (document: Document, key: string) => { @@ -132,7 +132,7 @@ class TreeView extends React.Component { protected createTreeDropTarget = (ele: HTMLDivElement) => { this._treedropDisposer && this._treedropDisposer(); - ele && (this._treedropDisposer = DragManager.MakeDropTarget(ele, { handlers: { drop: this.treeDrop.bind(this) } })); + ele && (this._treedropDisposer = DragManager.MakeDropTarget(ele, this.treeDrop.bind(this))); } onPointerDown = (e: React.PointerEvent) => e.stopPropagation(); @@ -220,25 +220,25 @@ class TreeView extends React.Component { const rect = this._header!.current!.getBoundingClientRect(); const before = pt[1] < rect.top + rect.height / 2; const inside = pt[0] > Math.min(rect.left + 75, rect.left + rect.width * .75) || (!before && this.treeViewOpen && DocListCast(this.dataDoc[this.fieldKey]).length); - if (de.data instanceof DragManager.LinkDragData) { - const sourceDoc = de.data.linkSourceDocument; + if (de.complete.linkDragData) { + const sourceDoc = de.complete.linkDragData.linkSourceDocument; const destDoc = this.props.document; DocUtils.MakeLink({ doc: sourceDoc }, { doc: destDoc }); e.stopPropagation(); } - if (de.data instanceof DragManager.DocumentDragData) { + if (de.complete.docDragData) { e.stopPropagation(); - if (de.data.draggedDocuments[0] === this.props.document) return true; + if (de.complete.docDragData.draggedDocuments[0] === this.props.document) return true; let addDoc = (doc: Doc) => this.props.addDocument(doc, undefined, before); if (inside) { addDoc = (doc: Doc) => Doc.AddDocToList(this.dataDoc, this.fieldKey, doc) || addDoc(doc); } - const movedDocs = (de.data.options === this.props.treeViewId ? de.data.draggedDocuments : de.data.droppedDocuments); - return ((de.data.dropAction && (de.data.options !== this.props.treeViewId)) || de.data.userDropAction) ? - de.data.droppedDocuments.reduce((added, d) => addDoc(d) || added, false) - : de.data.moveDocument ? - movedDocs.reduce((added, d) => de.data.moveDocument(d, undefined, addDoc) || added, false) - : de.data.droppedDocuments.reduce((added, d) => addDoc(d), false); + const movedDocs = (de.complete.docDragData.treeViewId === this.props.treeViewId ? de.complete.docDragData.draggedDocuments : de.complete.docDragData.droppedDocuments); + return ((de.complete.docDragData.dropAction && (de.complete.docDragData.treeViewId !== this.props.treeViewId)) || de.complete.docDragData.userDropAction) ? + de.complete.docDragData.droppedDocuments.reduce((added, d) => addDoc(d) || added, false) + : de.complete.docDragData.moveDocument ? + movedDocs.reduce((added, d) => de.complete.docDragData?.moveDocument?.(d, undefined, addDoc) || added, false) + : de.complete.docDragData.droppedDocuments.reduce((added, d) => addDoc(d), false); } return false; } @@ -571,7 +571,7 @@ export class CollectionTreeView extends CollectionSubView(Document) { protected createTreeDropTarget = (ele: HTMLDivElement) => { this.treedropDisposer && this.treedropDisposer(); if (this._mainEle = ele) { - this.treedropDisposer = DragManager.MakeDropTarget(ele, { handlers: { drop: this.drop.bind(this) } }); + this.treedropDisposer = DragManager.MakeDropTarget(ele, this.drop.bind(this)); } } @@ -624,7 +624,7 @@ export class CollectionTreeView extends CollectionSubView(Document) { render() { const dropAction = StrCast(this.props.Document.dropAction) as dropActionType; const addDoc = (doc: Doc, relativeTo?: Doc, before?: boolean) => Doc.AddDocToList(this.props.Document, this.props.fieldKey, doc, relativeTo, before, false, false, false); - const moveDoc = (d: Doc, target: Doc, addDoc: (doc: Doc) => boolean) => this.props.moveDocument(d, target, addDoc); + const moveDoc = (d: Doc, target: Doc | undefined, addDoc: (doc: Doc) => boolean) => this.props.moveDocument(d, target, addDoc); return !this.childDocs ? (null) : (
boolean; removeDocument: (document: Doc) => boolean; - moveDocument: (document: Doc, targetCollection: Doc, addDocument: (document: Doc) => boolean) => boolean; + moveDocument: (document: Doc, targetCollection: Doc | undefined, addDocument: (document: Doc) => boolean) => boolean; active: () => boolean; whenActiveChanged: (isActive: boolean) => void; } @@ -150,7 +150,7 @@ export class CollectionView extends Touchable { // otherwise, the document being moved must be able to be removed from its container before // moving it into the target. @action.bound - moveDocument(doc: Doc, targetCollection: Doc, addDocument: (doc: Doc) => boolean): boolean { + moveDocument(doc: Doc, targetCollection: Doc | undefined, addDocument: (doc: Doc) => boolean): boolean { if (Doc.AreProtosEqual(this.props.Document, targetCollection)) { return true; } diff --git a/src/client/views/collections/CollectionViewChromes.tsx b/src/client/views/collections/CollectionViewChromes.tsx index 4161e5d6e..a870b6043 100644 --- a/src/client/views/collections/CollectionViewChromes.tsx +++ b/src/client/views/collections/CollectionViewChromes.tsx @@ -288,15 +288,15 @@ export class CollectionViewBaseChrome extends React.Component { this.dropDisposer && this.dropDisposer(); if (ele) { - this.dropDisposer = DragManager.MakeDropTarget(ele, { handlers: { drop: this.drop.bind(this) } }); + this.dropDisposer = DragManager.MakeDropTarget(ele, this.drop.bind(this)); } } @undoBatch @action protected drop(e: Event, de: DragManager.DropEvent): boolean { - if (de.data instanceof DragManager.DocumentDragData && de.data.draggedDocuments.length) { - this._buttonizableCommands.filter(c => c.title === this._currentKey).map(c => c.immediate(de.data.draggedDocuments)); + if (de.complete.docDragData && de.complete.docDragData.draggedDocuments.length) { + this._buttonizableCommands.filter(c => c.title === this._currentKey).map(c => c.immediate(de.complete.docDragData?.draggedDocuments || [])); e.stopPropagation(); } return true; diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index ddfb52ba9..89c1df598 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -139,15 +139,15 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { const [xp, yp] = xf.transformPoint(de.x, de.y); const [xpo, ypo] = xfo.transformPoint(de.x, de.y); if (super.drop(e, de)) { - if (de.data instanceof DragManager.DocumentDragData) { - if (de.data.droppedDocuments.length) { - const firstDoc = de.data.droppedDocuments[0]; + if (de.complete.docDragData) { + if (de.complete.docDragData.droppedDocuments.length) { + const firstDoc = de.complete.docDragData.droppedDocuments[0]; const z = NumCast(firstDoc.z); - const x = (z ? xpo : xp) - de.data.offset[0]; - const y = (z ? ypo : yp) - de.data.offset[1]; + const x = (z ? xpo : xp) - de.complete.docDragData.offset[0]; + const y = (z ? ypo : yp) - de.complete.docDragData.offset[1]; const dropX = NumCast(firstDoc.x); const dropY = NumCast(firstDoc.y); - de.data.droppedDocuments.forEach(action((d: Doc) => { + de.complete.docDragData.droppedDocuments.forEach(action((d: Doc) => { const layoutDoc = Doc.Layout(d); d.x = x + NumCast(d.x) - dropX; d.y = y + NumCast(d.y) - dropY; @@ -162,19 +162,19 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { this.bringToFront(d); })); - de.data.droppedDocuments.length === 1 && this.updateCluster(de.data.droppedDocuments[0]); + de.complete.docDragData.droppedDocuments.length === 1 && this.updateCluster(de.complete.docDragData.droppedDocuments[0]); } } - else if (de.data instanceof DragManager.AnnotationDragData) { - if (de.data.dropDocument) { - const dragDoc = de.data.dropDocument; - const x = xp - de.data.offset[0]; - const y = yp - de.data.offset[1]; + else if (de.complete.annoDragData) { + if (de.complete.annoDragData.dropDocument) { + const dragDoc = de.complete.annoDragData.dropDocument; + const x = xp - de.complete.annoDragData.offset[0]; + const y = yp - de.complete.annoDragData.offset[1]; const dropX = NumCast(dragDoc.x); const dropY = NumCast(dragDoc.y); dragDoc.x = x + NumCast(dragDoc.x) - dropX; dragDoc.y = y + NumCast(dragDoc.y) - dropY; - de.data.targetContext = this.props.Document; // dropped a PDF annotation, so we need to set the targetContext on the dragData which the PDF view uses at the end of the drop operation + de.complete.annoDragData.targetContext = this.props.Document; // dropped a PDF annotation, so we need to set the targetContext on the dragData which the PDF view uses at the end of the drop operation this.bringToFront(dragDoc); } } @@ -205,10 +205,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { const [left, top] = clusterDocs[0].props.ScreenToLocalTransform().scale(clusterDocs[0].props.ContentScaling()).inverse().transformPoint(0, 0); de.offset = this.getTransform().transformDirection(ptsParent.clientX - left, ptsParent.clientY - top); de.dropAction = e.ctrlKey || e.altKey ? "alias" : undefined; - DragManager.StartDocumentDrag(clusterDocs.map(v => v.ContentDiv!), de, ptsParent.clientX, ptsParent.clientY, { - handlers: { dragComplete: action(emptyFunction) }, - hideSource: !de.dropAction - }); + DragManager.StartDocumentDrag(clusterDocs.map(v => v.ContentDiv!), de, ptsParent.clientX, ptsParent.clientY, { hideSource: !de.dropAction }); return true; } } @@ -896,7 +893,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { // otherwise, they are stored in fieldKey. All annotations to this document are stored in the extension document return !this.extensionDoc ? (null) :
diff --git a/src/client/views/linking/LinkMenu.scss b/src/client/views/linking/LinkMenu.scss index a4018bd2d..7dee22f66 100644 --- a/src/client/views/linking/LinkMenu.scss +++ b/src/client/views/linking/LinkMenu.scss @@ -48,90 +48,5 @@ } } -.linkMenu-item { - // border-top: 0.5px solid $main-accent; - position: relative; - display: flex; - font-size: 12px; - - - .link-name { - position: relative; - - p { - padding: 4px 6px; - line-height: 12px; - border-radius: 5px; - overflow-wrap: break-word; - } - } - - .linkMenu-item-content { - width: 100%; - } - - .link-metadata { - padding: 0 10px 0 16px; - margin-bottom: 4px; - color: $main-accent; - font-style: italic; - font-size: 10.5px; - } - - &:hover { - .linkMenu-item-buttons { - display: flex; - } - .linkMenu-item-content { - &.expand-two p { - width: calc(100% - 52px); - background-color: lightgray; - } - &.expand-three p { - width: calc(100% - 84px); - background-color: lightgray; - } - } - } -} - -.linkMenu-item-buttons { - display: none; - position: absolute; - top: 50%; - right: 0; - transform: translateY(-50%); - - .button { - width: 20px; - height: 20px; - margin: 0; - margin-right: 6px; - border-radius: 50%; - cursor: pointer; - pointer-events: auto; - background-color: $dark-color; - color: $light-color; - font-size: 65%; - transition: transform 0.2s; - text-align: center; - position: relative; - - .fa-icon { - position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - } - - &:last-child { - margin-right: 0; - } - &:hover { - background: $main-accent; - } - } -} - diff --git a/src/client/views/linking/LinkMenuGroup.tsx b/src/client/views/linking/LinkMenuGroup.tsx index 15aacbbc9..da56435f2 100644 --- a/src/client/views/linking/LinkMenuGroup.tsx +++ b/src/client/views/linking/LinkMenuGroup.tsx @@ -4,11 +4,9 @@ import { observer } from "mobx-react"; import { Doc } from "../../../new_fields/Doc"; import { Id } from "../../../new_fields/FieldSymbols"; import { SchemaHeaderField } from "../../../new_fields/SchemaHeaderField"; -import { emptyFunction } from "../../../Utils"; import { Docs } from "../../documents/Documents"; import { DragManager, SetupDrag } from "../../util/DragManager"; import { LinkManager } from "../../util/LinkManager"; -import { UndoManager } from "../../util/UndoManager"; import { DocumentView } from "../nodes/DocumentView"; import './LinkMenu.scss'; import { LinkMenuItem } from "./LinkMenuItem"; @@ -21,7 +19,6 @@ interface LinkMenuGroupProps { showEditor: (linkDoc: Doc) => void; addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => boolean; docView: DocumentView; - } @observer @@ -44,27 +41,14 @@ export class LinkMenuGroup extends React.Component { e.stopPropagation(); } - onLinkButtonMoved = async (e: PointerEvent) => { - UndoManager.RunInBatch(() => { - if (this._drag.current !== null && (e.movementX > 1 || e.movementY > 1)) { - document.removeEventListener("pointermove", this.onLinkButtonMoved); - document.removeEventListener("pointerup", this.onLinkButtonUp); + if (this._drag.current && (e.movementX > 1 || e.movementY > 1)) { + document.removeEventListener("pointermove", this.onLinkButtonMoved); + document.removeEventListener("pointerup", this.onLinkButtonUp); - const draggedDocs = this.props.group.map(linkDoc => { - const opp = LinkManager.Instance.getOppositeAnchor(linkDoc, this.props.sourceDoc); - if (opp) return opp; - }) as Doc[]; - const dragData = new DragManager.DocumentDragData(draggedDocs); - - DragManager.StartLinkedDocumentDrag([this._drag.current], dragData, e.x, e.y, { - handlers: { - dragComplete: action(emptyFunction), - }, - hideSource: false - }); - } - }, "drag links"); + let targets = this.props.group.map(l => LinkManager.Instance.getOppositeAnchor(l, this.props.sourceDoc)).filter(d => d) as Doc[]; + DragManager.StartLinkTargetsDrag(this._drag.current!, e.x, e.y, this.props.sourceDoc, targets); + } e.stopPropagation(); } diff --git a/src/client/views/linking/LinkMenuItem.scss b/src/client/views/linking/LinkMenuItem.scss new file mode 100644 index 000000000..fd0954f65 --- /dev/null +++ b/src/client/views/linking/LinkMenuItem.scss @@ -0,0 +1,87 @@ +@import "../globalCssVariables"; + +.linkMenu-item { + // border-top: 0.5px solid $main-accent; + position: relative; + display: flex; + font-size: 12px; + + + .linkMenu-name { + position: relative; + + p { + padding: 4px 6px; + line-height: 12px; + border-radius: 5px; + overflow-wrap: break-word; + user-select: none; + } + } + + .linkMenu-item-content { + width: 100%; + } + + .link-metadata { + padding: 0 10px 0 16px; + margin-bottom: 4px; + color: $main-accent; + font-style: italic; + font-size: 10.5px; + } + + &:hover { + .linkMenu-item-buttons { + display: flex; + } + .linkMenu-item-content { + &.expand-two p { + width: calc(100% - 52px); + background-color: lightgray; + } + &.expand-three p { + width: calc(100% - 84px); + background-color: lightgray; + } + } + } +} + +.linkMenu-item-buttons { + display: none; + position: absolute; + top: 50%; + right: 0; + transform: translateY(-50%); + + .button { + width: 20px; + height: 20px; + margin: 0; + margin-right: 6px; + border-radius: 50%; + cursor: pointer; + pointer-events: auto; + background-color: $dark-color; + color: $light-color; + font-size: 65%; + transition: transform 0.2s; + text-align: center; + position: relative; + + .fa-icon { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + } + + &:last-child { + margin-right: 0; + } + &:hover { + background: $main-accent; + } + } +} \ No newline at end of file diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx index edf5e9c26..b7d27ee30 100644 --- a/src/client/views/linking/LinkMenuItem.tsx +++ b/src/client/views/linking/LinkMenuItem.tsx @@ -5,11 +5,11 @@ import { action, observable } from 'mobx'; import { observer } from "mobx-react"; import { Doc } from '../../../new_fields/Doc'; import { Cast, StrCast } from '../../../new_fields/Types'; -import { DragLinkAsDocument } from '../../util/DragManager'; +import { DragManager } from '../../util/DragManager'; import { LinkManager } from '../../util/LinkManager'; import { ContextMenu } from '../ContextMenu'; import { LinkFollowBox } from './LinkFollowBox'; -import './LinkMenu.scss'; +import './LinkMenuItem.scss'; import React = require("react"); library.add(faEye, faEdit, faTimes, faArrowRight, faChevronDown, faChevronUp); @@ -26,6 +26,9 @@ interface LinkMenuItemProps { @observer export class LinkMenuItem extends React.Component { private _drag = React.createRef(); + private _downX = 0; + private _downY = 0; + private _eleClone: any; @observable private _showMore: boolean = false; @action toggleShowMore() { this._showMore = !this._showMore; } @@ -55,6 +58,9 @@ export class LinkMenuItem extends React.Component { } onLinkButtonDown = (e: React.PointerEvent): void => { + this._downX = e.clientX; + this._downY = e.clientY; + this._eleClone = this._drag.current!.cloneNode(true); e.stopPropagation(); document.removeEventListener("pointermove", this.onLinkButtonMoved); document.addEventListener("pointermove", this.onLinkButtonMoved); @@ -75,11 +81,12 @@ export class LinkMenuItem extends React.Component { } onLinkButtonMoved = async (e: PointerEvent) => { - if (this._drag.current !== null && (e.movementX > 1 || e.movementY > 1)) { + if (this._drag.current !== null && Math.abs((e.clientX - this._downX) * (e.clientX - this._downX) + (e.clientY - this._downY) * (e.clientY - this._downY)) > 5) { document.removeEventListener("pointermove", this.onLinkButtonMoved); document.removeEventListener("pointerup", this.onLinkButtonUp); - DragLinkAsDocument(this._drag.current, e.x, e.y, this.props.linkDoc, this.props.sourceDoc); + this._eleClone.style.transform = `translate(${e.x}px, ${e.y}px)`; + DragManager.StartLinkTargetsDrag(this._eleClone, e.x, e.y, this.props.sourceDoc, [this.props.linkDoc]); } e.stopPropagation(); } @@ -109,20 +116,21 @@ export class LinkMenuItem extends React.Component { } render() { - const keys = LinkManager.Instance.getMetadataKeysInGroup(this.props.groupType);//groupMetadataKeys.get(this.props.groupType); const canExpand = keys ? keys.length > 0 : false; return (
-
-

{StrCast(this.props.destinationDoc.title)}

+
+

{StrCast(this.props.destinationDoc.title)}

{canExpand ?
this.toggleShowMore()}>
: <>}
-
+
+ +
{this._showMore ? this.renderMetadata() : <>} diff --git a/src/client/views/nodes/ButtonBox.tsx b/src/client/views/nodes/ButtonBox.tsx index 34151a311..d1272c266 100644 --- a/src/client/views/nodes/ButtonBox.tsx +++ b/src/client/views/nodes/ButtonBox.tsx @@ -46,7 +46,7 @@ export class ButtonBox extends DocComponent(Butt this.dropDisposer(); } if (ele) { - this.dropDisposer = DragManager.MakeDropTarget(ele, { handlers: { drop: this.drop.bind(this) } }); + this.dropDisposer = DragManager.MakeDropTarget(ele, this.drop.bind(this)); } } @@ -65,9 +65,10 @@ export class ButtonBox extends DocComponent(Butt @undoBatch @action drop = (e: Event, de: DragManager.DropEvent) => { - if (de.data instanceof DragManager.DocumentDragData && e.target) { - this.props.Document[(e.target as any).textContent] = new List(de.data.droppedDocuments.map((d, i) => - d.onDragStart ? de.data.draggedDocuments[i] : d)); + const docDragData = de.complete.docDragData; + if (docDragData && e.target) { + this.props.Document[(e.target as any).textContent] = new List(docDragData.droppedDocuments.map((d, i) => + d.onDragStart ? docDragData.draggedDocuments[i] : d)); e.stopPropagation(); } } diff --git a/src/client/views/nodes/ContentFittingDocumentView.tsx b/src/client/views/nodes/ContentFittingDocumentView.tsx index 6d0ea33fa..5e3306a11 100644 --- a/src/client/views/nodes/ContentFittingDocumentView.tsx +++ b/src/client/views/nodes/ContentFittingDocumentView.tsx @@ -32,7 +32,7 @@ interface ContentFittingDocumentViewProps { onClick?: ScriptField; getTransform: () => Transform; addDocument: (document: Doc) => boolean; - moveDocument: (document: Doc, target: Doc, addDoc: ((doc: Doc) => boolean)) => boolean; + moveDocument: (document: Doc, target: Doc | undefined, addDoc: ((doc: Doc) => boolean)) => boolean; removeDocument: (document: Doc) => boolean; active: (outsideReaction: boolean) => boolean; whenActiveChanged: (isActive: boolean) => void; @@ -60,11 +60,12 @@ export class ContentFittingDocumentView extends React.Component { - if (de.data instanceof DragManager.DocumentDragData) { + const docDragData = de.complete.docDragData; + if (docDragData) { this.props.childDocs && this.props.childDocs.map(otherdoc => { const target = Doc.GetProto(otherdoc); target.layout = ComputedField.MakeFunction("this.image_data[0]"); - target.layoutCustom = Doc.MakeDelegate(de.data.draggedDocuments[0]); + target.layoutCustom = Doc.MakeDelegate(docDragData.draggedDocuments[0]); }); e.stopPropagation(); } diff --git a/src/client/views/nodes/DocuLinkBox.tsx b/src/client/views/nodes/DocuLinkBox.tsx index a22472e9e..3e2e74c67 100644 --- a/src/client/views/nodes/DocuLinkBox.tsx +++ b/src/client/views/nodes/DocuLinkBox.tsx @@ -5,7 +5,7 @@ import { makeInterface } from "../../../new_fields/Schema"; import { NumCast, StrCast, Cast } from "../../../new_fields/Types"; import { Utils } from '../../../Utils'; import { DocumentManager } from "../../util/DocumentManager"; -import { DragLinksAsDocuments } from "../../util/DragManager"; +import { DragManager } from "../../util/DragManager"; import { DocComponent } from "../DocComponent"; import "./DocuLinkBox.scss"; import { FieldView, FieldViewProps } from "./FieldView"; @@ -43,7 +43,7 @@ export class DocuLinkBox extends DocComponent(Doc const separation = Math.sqrt((pt[0] - e.clientX) * (pt[0] - e.clientX) + (pt[1] - e.clientY) * (pt[1] - e.clientY)); const dragdist = Math.sqrt((pt[0] - this._downx) * (pt[0] - this._downx) + (pt[1] - this._downy) * (pt[1] - this._downy)); if (separation > 100) { - DragLinksAsDocuments(this._ref.current!, pt[0], pt[1], Cast(this.props.Document[this.props.fieldKey], Doc) as Doc, this.props.Document); // Containging collection is the document, not a collection... hack. + DragManager.StartLinkTargetsDrag(this._ref.current!, pt[0], pt[1], Cast(this.props.Document[this.props.fieldKey], Doc) as Doc, [this.props.Document]); // Containging collection is the document, not a collection... hack. document.removeEventListener("pointermove", this.onPointerMove); document.removeEventListener("pointerup", this.onPointerUp); } else if (dragdist > separation) { diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 1b2d92027..b096d68fc 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -19,7 +19,6 @@ import { DocumentType } from '../../documents/DocumentTypes'; import { ClientUtils } from '../../util/ClientUtils'; import { DocumentManager } from "../../util/DocumentManager"; import { DragManager, dropActionType } from "../../util/DragManager"; -import { LinkManager } from '../../util/LinkManager'; import { Scripting } from '../../util/Scripting'; import { SelectionManager } from "../../util/SelectionManager"; import SharingManager from '../../util/SharingManager'; @@ -60,7 +59,7 @@ export interface DocumentViewProps { dragDivName?: string; addDocument?: (doc: Doc) => boolean; removeDocument?: (doc: Doc) => boolean; - moveDocument?: (doc: Doc, targetCollection: Doc, addDocument: (document: Doc) => boolean) => boolean; + moveDocument?: (doc: Doc, targetCollection: Doc | undefined, addDocument: (document: Doc) => boolean) => boolean; ScreenToLocalTransform: () => Transform; renderDepth: number; showOverlays?: (doc: Doc) => { title?: string, caption?: string }; @@ -105,7 +104,7 @@ export class DocumentView extends DocComponent(Docu @action componentDidMount() { - this._mainCont.current && (this._dropDisposer = DragManager.MakeDropTarget(this._mainCont.current, { handlers: { drop: this.drop.bind(this) } })); + this._mainCont.current && (this._dropDisposer = DragManager.MakeDropTarget(this._mainCont.current, this.drop.bind(this))); !this.props.dontRegisterView && DocumentManager.Instance.DocumentViews.push(this); } @@ -113,7 +112,7 @@ export class DocumentView extends DocComponent(Docu @action componentDidUpdate() { this._dropDisposer && this._dropDisposer(); - this._mainCont.current && (this._dropDisposer = DragManager.MakeDropTarget(this._mainCont.current, { handlers: { drop: this.drop.bind(this) } })); + this._mainCont.current && (this._dropDisposer = DragManager.MakeDropTarget(this._mainCont.current, this.drop.bind(this))); } @action @@ -132,12 +131,7 @@ export class DocumentView extends DocComponent(Docu dragData.moveDocument = this.Document.onDragStart ? undefined : this.props.moveDocument; dragData.applyAsTemplate = applyAsTemplate; dragData.dragDivName = this.props.dragDivName; - DragManager.StartDocumentDrag([this._mainCont.current], dragData, x, y, { - handlers: { - dragComplete: action((emptyFunction)) - }, - hideSource: !dropAction && !this.Document.onDragStart - }); + DragManager.StartDocumentDrag([this._mainCont.current], dragData, x, y, { hideSource: !dropAction && !this.Document.onDragStart }); } } @@ -190,7 +184,7 @@ export class DocumentView extends DocComponent(Docu buttonClick = async (altKey: boolean, ctrlKey: boolean) => { const maximizedDocs = await DocListCastAsync(this.Document.maximizedDocs); const summarizedDocs = await DocListCastAsync(this.Document.summarizedDocs); - const linkDocs = LinkManager.Instance.getAllRelatedLinks(this.props.Document); + const linkDocs = DocListCast(this.props.Document.links); let expandedDocs: Doc[] = []; expandedDocs = maximizedDocs ? [...maximizedDocs, ...expandedDocs] : expandedDocs; expandedDocs = summarizedDocs ? [...summarizedDocs, ...expandedDocs] : expandedDocs; @@ -324,23 +318,24 @@ export class DocumentView extends DocComponent(Docu @undoBatch @action drop = async (e: Event, de: DragManager.DropEvent) => { - if (de.data instanceof DragManager.AnnotationDragData) { + if (de.complete.annoDragData) { /// this whole section for handling PDF annotations looks weird. Need to rethink this to make it cleaner e.stopPropagation(); - (de.data as any).linkedToDoc = true; + de.complete.annoDragData.linkedToDoc = true; - DocUtils.MakeLink({ doc: de.data.annotationDocument }, { doc: this.props.Document, ctx: this.props.ContainingCollectionDoc }, `Link from ${StrCast(de.data.annotationDocument.title)}`); + DocUtils.MakeLink({ doc: de.complete.annoDragData.annotationDocument }, { doc: this.props.Document, ctx: this.props.ContainingCollectionDoc }, + `Link from ${StrCast(de.complete.annoDragData.annotationDocument.title)}`); } - if (de.data instanceof DragManager.DocumentDragData && de.data.applyAsTemplate) { - Doc.ApplyTemplateTo(de.data.draggedDocuments[0], this.props.Document, "layoutCustom"); + if (de.complete.docDragData && de.complete.docDragData.applyAsTemplate) { + Doc.ApplyTemplateTo(de.complete.docDragData.draggedDocuments[0], this.props.Document, "layoutCustom"); e.stopPropagation(); } - if (de.data instanceof DragManager.LinkDragData) { + if (de.complete.linkDragData) { e.stopPropagation(); // const docs = await SearchUtil.Search(`data_l:"${destDoc[Id]}"`, true); // const views = docs.map(d => DocumentManager.Instance.getDocumentView(d)).filter(d => d).map(d => d as DocumentView); - de.data.linkSourceDocument !== this.props.Document && - (de.data.linkDocument = DocUtils.MakeLink({ doc: de.data.linkSourceDocument }, { doc: this.props.Document, ctx: this.props.ContainingCollectionDoc }, "in-text link being created")); // TODODO this is where in text links get passed + de.complete.linkDragData.linkSourceDocument !== this.props.Document && + (de.complete.linkDragData.linkDocument = DocUtils.MakeLink({ doc: de.complete.linkDragData.linkSourceDocument }, { doc: this.props.Document, ctx: this.props.ContainingCollectionDoc }, "in-text link being created")); // TODODO this is where in text links get passed } } diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx index ce1c468ad..c56fde186 100644 --- a/src/client/views/nodes/FieldView.tsx +++ b/src/client/views/nodes/FieldView.tsx @@ -39,7 +39,7 @@ export interface FieldViewProps { addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => boolean; pinToPres: (document: Doc) => void; removeDocument?: (document: Doc) => boolean; - moveDocument?: (document: Doc, targetCollection: Doc, addDocument: (document: Doc) => boolean) => boolean; + moveDocument?: (document: Doc, targetCollection: Doc | undefined, addDocument: (document: Doc) => boolean) => boolean; ScreenToLocalTransform: () => Transform; active: (outsideReaction?: boolean) => boolean; whenActiveChanged: (isActive: boolean) => void; diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index 7d404b28f..af09e57f4 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -246,22 +246,22 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & protected createDropTarget = (ele: HTMLDivElement) => { this._proseRef = ele; this.dropDisposer && this.dropDisposer(); - ele && (this.dropDisposer = DragManager.MakeDropTarget(ele, { handlers: { drop: this.drop.bind(this) } })); + ele && (this.dropDisposer = DragManager.MakeDropTarget(ele, this.drop.bind(this))); } @undoBatch @action drop = async (e: Event, de: DragManager.DropEvent) => { - if (de.data instanceof DragManager.DocumentDragData) { - const draggedDoc = de.data.draggedDocuments.length && de.data.draggedDocuments[0]; + if (de.complete.docDragData) { + const draggedDoc = de.complete.docDragData.draggedDocuments.length && de.complete.docDragData.draggedDocuments[0]; // replace text contents whend dragging with Alt - if (draggedDoc && draggedDoc.type === DocumentType.TEXT && !Doc.AreProtosEqual(draggedDoc, this.props.Document) && de.mods === "AltKey") { + if (draggedDoc && draggedDoc.type === DocumentType.TEXT && !Doc.AreProtosEqual(draggedDoc, this.props.Document) && de.altKey) { if (draggedDoc.data instanceof RichTextField) { Doc.GetProto(this.dataDoc)[this.props.fieldKey] = new RichTextField(draggedDoc.data.Data, draggedDoc.data.Text); e.stopPropagation(); } // apply as template when dragging with Meta - } else if (draggedDoc && draggedDoc.type === DocumentType.TEXT && !Doc.AreProtosEqual(draggedDoc, this.props.Document) && de.mods === "MetaKey") { + } else if (draggedDoc && draggedDoc.type === DocumentType.TEXT && !Doc.AreProtosEqual(draggedDoc, this.props.Document) && de.metaKey) { draggedDoc.isTemplateDoc = true; let newLayout = Doc.Layout(draggedDoc); if (typeof (draggedDoc.layout) === "string") { @@ -272,8 +272,8 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & this.Document.layoutKey = "layoutCustom"; e.stopPropagation(); // embed document when dragging with a userDropAction or an embedDoc flag set - } else if (de.data.userDropAction || de.data.embedDoc) { - const target = de.data.droppedDocuments[0]; + } else if (de.complete.docDragData.userDropAction || de.complete.docDragData.embedDoc) { + const target = de.complete.docDragData.droppedDocuments[0]; // const link = DocUtils.MakeLink({ doc: this.dataDoc, ctx: this.props.ContainingCollectionDoc }, { doc: target }, "Embedded Doc:" + target.title); // if (link) { target.fitToBox = true; diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index 4b3da3dae..f6aa47f15 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -67,18 +67,18 @@ export class ImageBox extends DocAnnotatableComponent { this._dropDisposer && this._dropDisposer(); - ele && (this._dropDisposer = DragManager.MakeDropTarget(ele, { handlers: { drop: this.drop.bind(this) } })); + ele && (this._dropDisposer = DragManager.MakeDropTarget(ele, this.drop.bind(this))); } @undoBatch @action drop = (e: Event, de: DragManager.DropEvent) => { - if (de.data instanceof DragManager.DocumentDragData) { - if (de.mods === "AltKey" && de.data.draggedDocuments.length && de.data.draggedDocuments[0].data instanceof ImageField) { - Doc.GetProto(this.dataDoc)[this.props.fieldKey] = new ImageField(de.data.draggedDocuments[0].data.url); + if (de.complete.docDragData) { + if (de.altKey && de.complete.docDragData.draggedDocuments.length && de.complete.docDragData.draggedDocuments[0].data instanceof ImageField) { + Doc.GetProto(this.dataDoc)[this.props.fieldKey] = new ImageField(de.complete.docDragData.draggedDocuments[0].data.url); e.stopPropagation(); } - de.mods === "MetaKey" && de.data.droppedDocuments.forEach(action((drop: Doc) => { + de.metaKey && de.complete.docDragData.droppedDocuments.forEach(action((drop: Doc) => { this.extensionDoc && Doc.AddDocToList(Doc.GetProto(this.extensionDoc), "Alternates", drop); e.stopPropagation(); })); diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index b114cd7ed..c85350264 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -409,6 +409,7 @@ export class PDFViewer extends DocAnnotatableComponent !(dragData as any).linkedToDoc && - DocUtils.MakeLink({ doc: annotationDoc }, { doc: dragData.dropDocument, ctx: dragData.targetContext }, `Annotation from ${this.Document.title}`, "link from PDF") - - }, - hideSource: false + DragManager.StartPdfAnnoDrag([ele], new DragManager.PdfAnnoDragData(this.props.Document, annotationDoc, targetDoc), e.pageX, e.pageY, { + dragComplete: e => !e.aborted && e.annoDragData && !e.annoDragData.linkedToDoc && + DocUtils.MakeLink({ doc: annotationDoc }, { doc: e.annoDragData.dropDocument, ctx: e.annoDragData.targetContext }, `Annotation from ${this.Document.title}`, "link from PDF") }); } } diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index fe21c29c3..515c248f7 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -12,13 +12,11 @@ import { Utils } from '../../../Utils'; import { Docs } from '../../documents/Documents'; import { SetupDrag } from '../../util/DragManager'; import { SearchUtil } from '../../util/SearchUtil'; -import { MainView } from '../MainView'; import { FilterBox } from './FilterBox'; import "./FilterBox.scss"; import "./SearchBox.scss"; import { SearchItem } from './SearchItem'; import { IconBar } from './IconBar'; -import { string } from 'prop-types'; library.add(faTimes); diff --git a/src/client/views/search/SearchItem.tsx b/src/client/views/search/SearchItem.tsx index cdb6dcf7c..8cd4b3caa 100644 --- a/src/client/views/search/SearchItem.tsx +++ b/src/client/views/search/SearchItem.tsx @@ -4,14 +4,13 @@ import { faCaretUp, faChartBar, faFile, faFilePdf, faFilm, faFingerprint, faGlob import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { action, computed, observable, runInAction } from "mobx"; import { observer } from "mobx-react"; -import { Doc } from "../../../new_fields/Doc"; +import { Doc, DocListCast } from "../../../new_fields/Doc"; import { Id } from "../../../new_fields/FieldSymbols"; import { Cast, NumCast, StrCast } from "../../../new_fields/Types"; import { emptyFunction, returnEmptyString, returnFalse, returnOne, Utils, emptyPath } from "../../../Utils"; import { DocumentType } from "../../documents/DocumentTypes"; import { DocumentManager } from "../../util/DocumentManager"; import { DragManager, SetupDrag } from "../../util/DragManager"; -import { LinkManager } from "../../util/LinkManager"; import { SearchUtil } from "../../util/SearchUtil"; import { Transform } from "../../util/Transform"; import { SEARCH_THUMBNAIL_SIZE } from "../../views/globalCssVariables.scss"; @@ -211,7 +210,7 @@ export class SearchItem extends React.Component { } @computed - get linkCount() { return LinkManager.Instance.getAllRelatedLinks(this.props.doc).length; } + get linkCount() { return DocListCast(this.props.doc.links).length; } @action pointerDown = (e: React.PointerEvent) => { e.preventDefault(); e.button === 0 && SearchBox.Instance.openSearch(e); } @@ -267,10 +266,7 @@ export class SearchItem extends React.Component { onPointerDown = (e: React.PointerEvent) => { e.stopPropagation(); const doc = Doc.IsPrototype(this.props.doc) ? Doc.MakeDelegate(this.props.doc) : this.props.doc; - DragManager.StartDocumentDrag([e.currentTarget], new DragManager.DocumentDragData([doc]), e.clientX, e.clientY, { - handlers: { dragComplete: emptyFunction }, - hideSource: false, - }); + DragManager.StartDocumentDrag([e.currentTarget], new DragManager.DocumentDragData([doc]), e.clientX, e.clientY); } render() { -- cgit v1.2.3-70-g09d2 From d281270053e2c0edb2cb761dd1cbce6306369863 Mon Sep 17 00:00:00 2001 From: Sam Wilkins Date: Sun, 19 Jan 2020 23:07:08 -0500 Subject: further adjustments to import script --- src/client/views/nodes/FieldView.tsx | 2 +- src/scraping/buxton/scraper.py | 44 ++++++++++++++++++++++++------------ 2 files changed, 30 insertions(+), 16 deletions(-) (limited to 'src/client/views/nodes/FieldView.tsx') diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx index c56fde186..6e6ee1712 100644 --- a/src/client/views/nodes/FieldView.tsx +++ b/src/client/views/nodes/FieldView.tsx @@ -54,7 +54,7 @@ export interface FieldViewProps { @observer export class FieldView extends React.Component { public static LayoutString(fieldType: { name: string }, fieldStr: string) { - return `<${fieldType.name} {...props} fieldKey={'${fieldStr}'}/>`; //e.g., "" + return `<${fieldType.name} {...props} fieldKey={'${fieldStr}'}/>`; //e.g., "" } @computed diff --git a/src/scraping/buxton/scraper.py b/src/scraping/buxton/scraper.py index 90205c40b..15b5844f7 100644 --- a/src/scraping/buxton/scraper.py +++ b/src/scraping/buxton/scraper.py @@ -71,7 +71,7 @@ def text_doc_map(string_list): return listify(proxify_guids(list(map(guid_map, string_list)))) -def write_collection(parse_results, display_fields, storage_key, viewType=2): +def write_collection(parse_results, display_fields, storage_key, viewType): view_guids = parse_results["child_guids"] data_doc = parse_results["schema"] @@ -107,6 +107,11 @@ def write_collection(parse_results, display_fields, storage_key, viewType=2): "date": datetime.datetime.utcnow().microsecond, "__type": "date" } + if "image_urls" in parse_results: + fields["hero"] = { + "url": parse_results["image_urls"][0], + "__type": "image" + } fields["isPrototype"] = True fields["page"] = -1 @@ -176,6 +181,9 @@ def write_image(folder, name): image = Image.open(f"{image_dist}/{folder}/{name}") native_width, native_height = image.size + if abs(native_width - native_height) < 10: + return None + view_doc = { "_id": view_doc_guid, "fields": { @@ -214,7 +222,10 @@ def write_image(folder, name): target_collection.insert_one(view_doc) target_collection.insert_one(data_doc) - return view_doc_guid + return { + "layout_id": view_doc_guid, + "url": path + } def parse_document(file_name: str): @@ -229,16 +240,20 @@ def parse_document(file_name: str): raw = str(docx2txt.process(source + "/" + file_name, dir_path)) + urls = [] view_guids = [] count = 0 for image in os.listdir(dir_path): - count += 1 - view_guids.append(write_image(pure_name, image)) - resolved = dir_path + "/" + image - original = dir_path + "/" + image.replace(".", "_o.", 1) - medium = dir_path + "/" + image.replace(".", "_m.", 1) - copyfile(resolved, original) - copyfile(resolved, medium) + created = write_image(pure_name, image) + if created != None: + urls.append(created["url"]) + view_guids.append(created["layout_id"]) + count += 1 + resolved = dir_path + "/" + image + original = dir_path + "/" + image.replace(".", "_o.", 1) + medium = dir_path + "/" + image.replace(".", "_m.", 1) + copyfile(resolved, original) + copyfile(resolved, medium) print(f"extracted {count} images...") def sanitize(line): return re.sub("[\n\t]+", "", line).replace(u"\u00A0", " ").replace( @@ -345,7 +360,8 @@ def parse_document(file_name: str): "fields": result, "__type": "Doc" }, - "child_guids": view_guids + "child_guids": view_guids, + "image_urls": urls } @@ -359,13 +375,11 @@ def write_common_proto(): "_id": id, "fields": { "proto": protofy("collectionProto"), - "title": "Common Import Proto", + "title": "The Buxton Collection", }, "__type": "Doc" } - target_collection.insert_one(common_proto) - return id @@ -383,7 +397,7 @@ for file_name in os.listdir(source): if file_name.endswith('.docx'): candidates += 1 schema_guids.append(write_collection( - parse_document(file_name), ["title", "data"], "image_data")) + parse_document(file_name), ["title", "data"], "data", 5)) print("writing parent schema...") parent_guid = write_collection({ @@ -393,7 +407,7 @@ parent_guid = write_collection({ "__type": "Doc" }, "child_guids": schema_guids -}, ["title", "short_description", "original_price"], "data", 1) +}, ["title", "short_description", "original_price"], "data", 4) print("appending parent schema to main workspace...\n") target_collection.update_one( -- cgit v1.2.3-70-g09d2 From 0142f4e14cc8e291ee5acbae3cc4b81c95c4634a Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Thu, 23 Jan 2020 00:40:55 -0500 Subject: got rid of rule provider stuff. fixed panning in freeform view with pivot layouts --- src/client/util/RichTextMenu.tsx | 20 ++--------- src/client/util/RichTextRules.ts | 24 ------------- src/client/util/RichTextSchema.tsx | 1 - src/client/views/DocumentDecorations.tsx | 9 +---- src/client/views/GestureOverlay.tsx | 1 - src/client/views/InkingControl.tsx | 29 +-------------- src/client/views/MainView.tsx | 4 --- src/client/views/OverlayView.tsx | 1 - src/client/views/Palette.tsx | 1 - .../views/collections/CollectionDockingView.tsx | 1 - .../views/collections/CollectionLinearView.tsx | 1 - .../views/collections/CollectionSchemaCells.tsx | 1 - .../views/collections/CollectionSchemaView.tsx | 1 - .../views/collections/CollectionStackingView.tsx | 3 +- src/client/views/collections/CollectionSubView.tsx | 1 - .../views/collections/CollectionTreeView.tsx | 3 -- .../collectionFreeForm/CollectionFreeFormView.tsx | 42 +++++----------------- .../views/nodes/CollectionFreeFormDocumentView.tsx | 4 +-- .../views/nodes/ContentFittingDocumentView.tsx | 2 -- src/client/views/nodes/DocumentBox.tsx | 1 - src/client/views/nodes/DocumentView.tsx | 8 ++--- src/client/views/nodes/FieldView.tsx | 1 - src/client/views/nodes/FormattedTextBox.tsx | 33 ----------------- src/client/views/nodes/FormattedTextBoxComment.tsx | 1 - src/client/views/nodes/ImageBox.tsx | 1 - src/client/views/nodes/KeyValuePair.tsx | 1 - src/client/views/nodes/VideoBox.tsx | 1 - src/client/views/nodes/WebBox.tsx | 1 - src/client/views/pdf/PDFViewer.tsx | 1 - .../views/presentationview/PresElementBox.tsx | 1 - src/client/views/search/SearchItem.tsx | 1 - src/mobile/MobileInterface.tsx | 1 - 32 files changed, 16 insertions(+), 185 deletions(-) (limited to 'src/client/views/nodes/FieldView.tsx') diff --git a/src/client/util/RichTextMenu.tsx b/src/client/util/RichTextMenu.tsx index eb5c90654..e07efe056 100644 --- a/src/client/util/RichTextMenu.tsx +++ b/src/client/util/RichTextMenu.tsx @@ -367,27 +367,11 @@ export default class RichTextMenu extends AntimodeMenu { } changeFontSize = (mark: Mark, view: EditorView) => { - const size = mark.attrs.fontSize; - if (this.editorProps) { - const ruleProvider = this.editorProps.ruleProvider; - const heading = NumCast(this.editorProps.Document.heading); - if (ruleProvider && heading) { - ruleProvider["ruleSize_" + heading] = size; - } - } - this.setMark(view.state.schema.marks.pFontSize.create({ fontSize: size }), view.state, view.dispatch); + this.setMark(view.state.schema.marks.pFontSize.create({ fontSize: mark.attrs.fontSize }), view.state, view.dispatch); } changeFontFamily = (mark: Mark, view: EditorView) => { - const fontName = mark.attrs.family; - if (this.editorProps) { - const ruleProvider = this.editorProps.ruleProvider; - const heading = NumCast(this.editorProps.Document.heading); - if (ruleProvider && heading) { - ruleProvider["ruleFont_" + heading] = fontName; - } - } - this.setMark(view.state.schema.marks.pFontFamily.create({ family: fontName }), view.state, view.dispatch); + this.setMark(view.state.schema.marks.pFontFamily.create({ family: mark.attrs.family }), view.state, view.dispatch); } // TODO: remove doesn't work diff --git a/src/client/util/RichTextRules.ts b/src/client/util/RichTextRules.ts index e20abb04c..0ee9481f0 100644 --- a/src/client/util/RichTextRules.ts +++ b/src/client/util/RichTextRules.ts @@ -67,12 +67,6 @@ export const inpRules = { new RegExp(/^%([0-9]+)\s$/), (state, match, start, end) => { const size = Number(match[1]); - const ruleProvider = FormattedTextBox.FocusedBox!.props.ruleProvider; - const heading = NumCast(FormattedTextBox.FocusedBox!.props.Document.heading); - if (ruleProvider && heading) { - (Cast(FormattedTextBox.FocusedBox!.props.Document, Doc) as Doc).heading = size; - return state.tr.deleteRange(start, end); - } return state.tr.deleteRange(start, end).addStoredMark(schema.marks.pFontSize.create({ fontSize: size })); }), @@ -175,12 +169,6 @@ export const inpRules = { (state, match, start, end) => { const node = (state.doc.resolve(start) as any).nodeAfter; const sm = state.storedMarks || undefined; - const ruleProvider = FormattedTextBox.FocusedBox!.props.ruleProvider; - const heading = NumCast(FormattedTextBox.FocusedBox!.props.Document.heading); - if (ruleProvider && heading) { - ruleProvider["ruleAlign_" + heading] = "center"; - return node ? state.tr.deleteRange(start, end).setStoredMarks([...node.marks, ...(sm ? sm : [])]) : state.tr; - } const replaced = node ? state.tr.replaceRangeWith(start, end, schema.nodes.paragraph.create({ align: "center" })).setStoredMarks([...node.marks, ...(sm ? sm : [])]) : state.tr; return replaced.setSelection(new TextSelection(replaced.doc.resolve(end - 2))); @@ -191,12 +179,6 @@ export const inpRules = { (state, match, start, end) => { const node = (state.doc.resolve(start) as any).nodeAfter; const sm = state.storedMarks || undefined; - const ruleProvider = FormattedTextBox.FocusedBox!.props.ruleProvider; - const heading = NumCast(FormattedTextBox.FocusedBox!.props.Document.heading); - if (ruleProvider && heading) { - ruleProvider["ruleAlign_" + heading] = "left"; - return node ? state.tr.deleteRange(start, end).setStoredMarks([...node.marks, ...(sm ? sm : [])]) : state.tr; - } const replaced = node ? state.tr.replaceRangeWith(start, end, schema.nodes.paragraph.create({ align: "left" })).setStoredMarks([...node.marks, ...(sm ? sm : [])]) : state.tr; return replaced.setSelection(new TextSelection(replaced.doc.resolve(end - 2))); @@ -207,12 +189,6 @@ export const inpRules = { (state, match, start, end) => { const node = (state.doc.resolve(start) as any).nodeAfter; const sm = state.storedMarks || undefined; - const ruleProvider = FormattedTextBox.FocusedBox!.props.ruleProvider; - const heading = NumCast(FormattedTextBox.FocusedBox!.props.Document.heading); - if (ruleProvider && heading) { - ruleProvider["ruleAlign_" + heading] = "right"; - return node ? state.tr.deleteRange(start, end).setStoredMarks([...node.marks, ...(sm ? sm : [])]) : state.tr; - } const replaced = node ? state.tr.replaceRangeWith(start, end, schema.nodes.paragraph.create({ align: "right" })).setStoredMarks([...node.marks, ...(sm ? sm : [])]) : state.tr; return replaced.setSelection(new TextSelection(replaced.doc.resolve(end - 2))); diff --git a/src/client/util/RichTextSchema.tsx b/src/client/util/RichTextSchema.tsx index 5751c8c7e..fe7ab31a8 100644 --- a/src/client/util/RichTextSchema.tsx +++ b/src/client/util/RichTextSchema.tsx @@ -761,7 +761,6 @@ export class DashDocView { fitToBox={BoolCast(dashDoc.fitToBox)} addDocument={returnFalse} removeDocument={removeDoc} - ruleProvider={undefined} ScreenToLocalTransform={this.getDocTransform} addDocTab={self._textBox.props.addDocTab} pinToPres={returnFalse} diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 322536b7e..e6a119d1f 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -362,14 +362,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> onRadiusMove = (e: PointerEvent): void => { let dist = Math.sqrt((e.clientX - this._radiusDown[0]) * (e.clientX - this._radiusDown[0]) + (e.clientY - this._radiusDown[1]) * (e.clientY - this._radiusDown[1])); dist = dist < 3 ? 0 : dist; - let usingRule = false; - SelectionManager.SelectedDocuments().map(dv => { - const ruleProvider = dv.props.ruleProvider; - const heading = NumCast(dv.props.Document.heading); - ruleProvider && heading && (Doc.GetProto(ruleProvider)["ruleRounding_" + heading] = `${Math.min(100, dist)}%`); - usingRule = usingRule || (ruleProvider && heading ? true : false); - }); - !usingRule && SelectionManager.SelectedDocuments().map(dv => dv.props.Document.layout instanceof Doc ? dv.props.Document.layout : dv.props.Document.isTemplateForField ? dv.props.Document : Doc.GetProto(dv.props.Document)). + SelectionManager.SelectedDocuments().map(dv => dv.props.Document.layout instanceof Doc ? dv.props.Document.layout : dv.props.Document.isTemplateForField ? dv.props.Document : Doc.GetProto(dv.props.Document)). map(d => d.borderRounding = `${Math.min(100, dist)}%`); e.stopPropagation(); e.preventDefault(); diff --git a/src/client/views/GestureOverlay.tsx b/src/client/views/GestureOverlay.tsx index 84d089b47..580c53a37 100644 --- a/src/client/views/GestureOverlay.tsx +++ b/src/client/views/GestureOverlay.tsx @@ -462,7 +462,6 @@ export default class GestureOverlay extends Touchable { addDocTab={returnFalse} pinToPres={emptyFunction} onClick={undefined} - ruleProvider={undefined} removeDocument={undefined} ScreenToLocalTransform={() => new Transform(-(this._thumbX ?? 0), -(this._thumbY ?? 0) + this.height, 1)} ContentScaling={returnOne} diff --git a/src/client/views/InkingControl.tsx b/src/client/views/InkingControl.tsx index ab53b76be..10d013865 100644 --- a/src/client/views/InkingControl.tsx +++ b/src/client/views/InkingControl.tsx @@ -55,34 +55,7 @@ export class InkingControl { } const oldColor = StrCast(targetDoc.backgroundColor); let matchedColor = this._selectedColor; - const cvd = view.props.ContainingCollectionDoc; - let ruleProvider = view.props.ruleProvider; - // if (cvd) { - // if (!cvd.colorPalette) { - // const defaultPalette = ["rg(114,229,239)", "rgb(255,246,209)", "rgb(255,188,156)", "rgb(247,220,96)", "rgb(122,176,238)", - // "rgb(209,150,226)", "rgb(127,235,144)", "rgb(252,188,189)", "rgb(247,175,81)",]; - // const colorPalette = Cast(cvd.colorPalette, listSpec("string")); - // if (!colorPalette) cvd.colorPalette = new List(defaultPalette); - // } - // const cp = Cast(cvd.colorPalette, listSpec("string")) as string[]; - // let closest = 0; - // let dist = 10000000; - // const ccol = Utils.fromRGBAstr(StrCast(targetDoc.backgroundColor)); - // for (let i = 0; i < cp.length; i++) { - // const cpcol = Utils.fromRGBAstr(cp[i]); - // const d = Math.sqrt((ccol.r - cpcol.r) * (ccol.r - cpcol.r) + (ccol.b - cpcol.b) * (ccol.b - cpcol.b) + (ccol.g - cpcol.g) * (ccol.g - cpcol.g)); - // if (d < dist) { - // dist = d; - // closest = i; - // } - // } - // cp[closest] = "rgba(" + color.rgb.r + "," + color.rgb.g + "," + color.rgb.b + "," + color.rgb.a + ")"; - // cvd.colorPalette = new List(cp); - // matchedColor = cp[closest]; - // ruleProvider = (view.props.Document.heading && ruleProvider) ? ruleProvider : undefined; - // ruleProvider && ((Doc.GetProto(ruleProvider)["ruleColor_" + NumCast(view.props.Document.heading)] = Utils.toRGBAstr(color.rgb))); - // } - (!ruleProvider && targetDoc) && (Doc.Layout(view.props.Document).backgroundColor = matchedColor); + targetDoc && (Doc.Layout(view.props.Document).backgroundColor = matchedColor); return { target: targetDoc, diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 79e0cfea5..cd4e9a1a6 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -276,7 +276,6 @@ export class MainView extends React.Component { addDocTab={this.addDocTabFunc} pinToPres={emptyFunction} onClick={undefined} - ruleProvider={undefined} removeDocument={undefined} ScreenToLocalTransform={Transform.Identity} ContentScaling={returnOne} @@ -377,7 +376,6 @@ export class MainView extends React.Component { addDocTab={this.addDocTabFunc} pinToPres={emptyFunction} removeDocument={undefined} - ruleProvider={undefined} onClick={undefined} ScreenToLocalTransform={Transform.Identity} ContentScaling={returnOne} @@ -404,7 +402,6 @@ export class MainView extends React.Component { addDocTab={this.addDocTabFunc} pinToPres={emptyFunction} removeDocument={returnFalse} - ruleProvider={undefined} onClick={undefined} ScreenToLocalTransform={this.mainContainerXf} ContentScaling={returnOne} @@ -500,7 +497,6 @@ export class MainView extends React.Component { addDocTab={this.addDocTabFunc} pinToPres={emptyFunction} removeDocument={this.remButtonDoc} - ruleProvider={undefined} onClick={undefined} ScreenToLocalTransform={this.buttonBarXf} ContentScaling={returnOne} diff --git a/src/client/views/OverlayView.tsx b/src/client/views/OverlayView.tsx index 350a75d29..295cd7c6e 100644 --- a/src/client/views/OverlayView.tsx +++ b/src/client/views/OverlayView.tsx @@ -178,7 +178,6 @@ export class OverlayView extends React.Component { // select={emptyFunction} // layoutKey={"layout"} bringToFront={emptyFunction} - ruleProvider={undefined} addDocument={undefined} removeDocument={undefined} ContentScaling={returnOne} diff --git a/src/client/views/Palette.tsx b/src/client/views/Palette.tsx index 811c24f53..10aac96a0 100644 --- a/src/client/views/Palette.tsx +++ b/src/client/views/Palette.tsx @@ -56,7 +56,6 @@ export default class Palette extends React.Component { addDocTab={returnFalse} pinToPres={emptyFunction} removeDocument={undefined} - ruleProvider={undefined} onClick={undefined} ScreenToLocalTransform={Transform.Identity} ContentScaling={returnOne} diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 5f9b4e0c7..125cd828f 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -723,7 +723,6 @@ export class DockedFrameRenderer extends React.Component { bringToFront={emptyFunction} addDocument={undefined} removeDocument={undefined} - ruleProvider={undefined} ContentScaling={this.contentScaling} PanelWidth={this.panelWidth} PanelHeight={this.panelHeight} diff --git a/src/client/views/collections/CollectionLinearView.tsx b/src/client/views/collections/CollectionLinearView.tsx index 77af2dc0e..8bf6b4202 100644 --- a/src/client/views/collections/CollectionLinearView.tsx +++ b/src/client/views/collections/CollectionLinearView.tsx @@ -108,7 +108,6 @@ export class CollectionLinearView extends CollectionSubView(LinearDocument) { addDocTab={this.props.addDocTab} pinToPres={emptyFunction} removeDocument={this.props.removeDocument} - ruleProvider={undefined} onClick={undefined} ScreenToLocalTransform={this.getTransform(dref)} ContentScaling={returnOne} diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx index 79a34bc00..7e990ab4d 100644 --- a/src/client/views/collections/CollectionSchemaCells.tsx +++ b/src/client/views/collections/CollectionSchemaCells.tsx @@ -145,7 +145,6 @@ export class CollectionSchemaCell extends React.Component { DataDoc: this.props.rowProps.original, LibraryPath: [], fieldKey: this.props.rowProps.column.id as string, - ruleProvider: undefined, ContainingCollectionView: this.props.CollectionView, ContainingCollectionDoc: this.props.CollectionView && this.props.CollectionView.props.Document, isSelected: returnFalse, diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index b466d9511..994c7b351 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -144,7 +144,6 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { LibraryPath={this.props.LibraryPath} childDocs={this.childDocs} renderDepth={this.props.renderDepth} - ruleProvider={this.props.Document.isRuleProvider && layoutDoc && layoutDoc.type !== DocumentType.TEXT ? this.props.Document : this.props.ruleProvider} PanelWidth={this.previewWidth} PanelHeight={this.previewHeight} getTransform={this.getPreviewTransform} diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index b2e4b9d90..ec22bb813 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -39,7 +39,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { @observable _scroll = 0; // used to force the document decoration to update when scrolling @computed get sectionHeaders() { return Cast(this.props.Document.sectionHeaders, listSpec(SchemaHeaderField)); } @computed get sectionFilter() { return StrCast(this.props.Document.sectionFilter); } - @computed get filteredChildren() { return this.childDocs.filter(d => !d.isMinimized).map(d => (Doc.GetLayoutDataDocPair(this.props.Document, this.props.DataDoc, d).layout as Doc) || d); } + @computed get filteredChildren() { return this.childLayoutPairs.filter(pair => !pair.layout.isMinimized).map(pair => pair.layout); } @computed get xMargin() { return NumCast(this.props.Document.xMargin, 2 * this.gridGap); } @computed get yMargin() { return Math.max(this.props.Document.showTitle && !this.props.Document.showTitleHover ? 30 : 0, NumCast(this.props.Document.yMargin, 2 * this.gridGap)); } @computed get gridGap() { return NumCast(this.props.Document.gridGap, 10); } @@ -167,7 +167,6 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { LibraryPath={this.props.LibraryPath} showOverlays={this.overlays} renderDepth={this.props.renderDepth + 1} - ruleProvider={this.props.Document.isRuleProvider && layoutDoc.type !== DocumentType.TEXT ? this.props.Document : this.props.ruleProvider} fitToBox={this.props.fitToBox} onClick={layoutDoc.isTemplateDoc ? this.onClickHandler : this.onChildClickHandler} PanelWidth={width} diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 6c4f940b6..063b5c5df 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -40,7 +40,6 @@ export interface CollectionViewProps extends FieldViewProps { export interface SubCollectionViewProps extends CollectionViewProps { CollectionView: Opt; - ruleProvider: Doc | undefined; children?: never | (() => JSX.Element[]) | React.ReactNode; isAnnotationOverlay?: boolean; annotationsKey: string; diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 2c8c53f97..ec348e74b 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -43,7 +43,6 @@ export interface TreeViewProps { prevSibling?: Doc; renderDepth: number; deleteDoc: (doc: Doc) => boolean; - ruleProvider: Doc | undefined; moveDocument: DragManager.MoveFunction; dropAction: "alias" | "copy" | undefined; addDocTab: (doc: Doc, dataDoc: Doc | undefined, where: string, libraryPath?: Doc[]) => boolean; @@ -352,7 +351,6 @@ class TreeView extends React.Component { LibraryPath={emptyPath} renderDepth={this.props.renderDepth + 1} showOverlays={this.noOverlays} - ruleProvider={this.props.document.isRuleProvider && layoutDoc.type !== DocumentType.TEXT ? this.props.document : this.props.ruleProvider} fitToBox={this.boundsOfCollectionDocument !== undefined} PanelWidth={this.docWidth} PanelHeight={this.docHeight} @@ -559,7 +557,6 @@ class TreeView extends React.Component { containingCollection={containingCollection} prevSibling={docs[i]} treeViewId={treeViewId} - ruleProvider={containingCollection.isRuleProvider && pair.layout.type !== DocumentType.TEXT ? containingCollection : containingCollection.ruleProvider as Doc} key={child[Id]} indentDocument={indent} outdentDocument={outdent} diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index aa1559416..65953dbdc 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -54,7 +54,6 @@ export const panZoomSchema = createSchema({ arrangeScript: ScriptField, arrangeInit: ScriptField, useClusters: "boolean", - isRuleProvider: "boolean", fitToBox: "boolean", xPadding: "number", // pixels of padding on left/right of collectionfreeformview contents when fitToBox is set yPadding: "number", // pixels of padding on left/right of collectionfreeformview contents when fitToBox is set @@ -103,14 +102,6 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { private getLocalTransform = (): Transform => Transform.Identity().scale(1 / this.zoomScaling()).translate(this.panX(), this.panY()); private addLiveTextBox = (newBox: Doc) => { FormattedTextBox.SelectOnLoad = newBox[Id];// track the new text box so we can give it a prop that tells it to focus itself when it's displayed - const maxHeading = this.childDocs.reduce((maxHeading, doc) => NumCast(doc.heading) > maxHeading ? NumCast(doc.heading) : maxHeading, 0); - let heading = maxHeading === 0 || this.childDocs.length === 0 ? 1 : maxHeading === 1 ? 2 : 0; - if (heading === 0) { - const sorted = this.childDocs.filter(d => d.type === DocumentType.TEXT && d.data_ext instanceof Doc && d.data_ext.lastModified).sort((a, b) => DateCast((Cast(a.data_ext, Doc) as Doc).lastModified).date > DateCast((Cast(b.data_ext, Doc) as Doc).lastModified).date ? 1 : - DateCast((Cast(a.data_ext, Doc) as Doc).lastModified).date < DateCast((Cast(b.data_ext, Doc) as Doc).lastModified).date ? -1 : 0); - heading = !sorted.length ? Math.max(1, maxHeading) : NumCast(sorted[sorted.length - 1].heading) === 1 ? 2 : NumCast(sorted[sorted.length - 1].heading); - } - !this.Document.isRuleProvider && (newBox.heading = heading); this.addDocument(newBox); } private addDocument = (newBox: Doc) => { @@ -412,16 +403,16 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { const [dx, dy] = this.getTransform().transformDirection(e.clientX - this._lastX, e.clientY - this._lastY); if (!this.isAnnotationOverlay) { PDFMenu.Instance.fadeOut(true); - const minx = docs.length ? NumCast(docs[0].x) : 0; - const maxx = docs.length ? NumCast(docs[0].width) + minx : minx; - const miny = docs.length ? NumCast(docs[0].y) : 0; - const maxy = docs.length ? NumCast(docs[0].height) + miny : miny; + const minx = this.childDataProvider(docs[0]).x;//docs.length ? NumCast(docs[0].x) : 0; + const miny = this.childDataProvider(docs[0]).y;//docs.length ? NumCast(docs[0].y) : 0; + const maxx = this.childDataProvider(docs[0]).width + minx;//docs.length ? NumCast(docs[0].width) + minx : minx; + const maxy = this.childDataProvider(docs[0]).height + miny;//docs.length ? NumCast(docs[0].height) + miny : miny; const ranges = docs.filter(doc => doc).reduce((range, doc) => { const layoutDoc = Doc.Layout(doc); - const x = NumCast(doc.x); - const xe = x + NumCast(layoutDoc.width); - const y = NumCast(doc.y); - const ye = y + NumCast(layoutDoc.height); + const x = this.childDataProvider(doc).x;//NumCast(doc.x); + const y = this.childDataProvider(doc).y;//NumCast(doc.y); + const xe = this.childDataProvider(doc).width + x;//x + NumCast(layoutDoc.width); + const ye = this.childDataProvider(doc).height + y; //y + NumCast(layoutDoc.height); return [[range[0][0] > x ? x : range[0][0], range[0][1] < xe ? xe : range[0][1]], [range[1][0] > y ? y : range[1][0], range[1][1] < ye ? ye : range[1][1]]]; }, [[minx, maxx], [miny, maxy]]); @@ -694,7 +685,6 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { Document: childLayout, LibraryPath: this.libraryPath, layoutKey: undefined, - ruleProvider: this.Document.isRuleProvider && childLayout.type !== DocumentType.TEXT ? this.props.Document : this.props.ruleProvider, //bcz: hack! - currently ruleProviders apply to documents in nested colleciton, not direct children of themselves //onClick: undefined, // this.props.onClick, // bcz: check this out -- I don't think we want to inherit click handlers, or we at least need a way to ignore them onClick: this.onChildClickHandler, ScreenToLocalTransform: childLayout.z ? this.getTransformOverlay : this.getTransform, @@ -779,7 +769,6 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { computedElementData.elements.push({ ele: , bounds: this.childDataProvider(pair.layout) @@ -827,20 +816,6 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { }, "arrange contents"); } - autoFormat = () => { - this.Document.isRuleProvider = !this.Document.isRuleProvider; - // find rule colorations when rule providing is turned on by looking at each document to see if it has a coloring -- if so, use it's color as the rule for its associated heading. - this.Document.isRuleProvider && this.childLayoutPairs.map(pair => - // iterate over the children of a displayed document (or if the displayed document is a template, iterate over the children of that template) - DocListCast(Doc.Layout(pair.layout).data).map(heading => { - const headingPair = Doc.GetLayoutDataDocPair(this.props.Document, this.props.DataDoc, heading); - const headingLayout = headingPair.layout && (pair.layout.data_ext instanceof Doc) && (pair.layout.data_ext[`Layout[${headingPair.layout[Id]}]`] as Doc) || headingPair.layout; - if (headingLayout && NumCast(headingLayout.heading) > 0 && headingLayout.backgroundColor !== headingLayout.defaultBackgroundColor) { - Doc.GetProto(this.props.Document)["ruleColor_" + NumCast(headingLayout.heading)] = headingLayout.backgroundColor; - } - }) - ); - } analyzeStrokes = async () => { const children = await DocListCastAsync(this.dataDoc.data); @@ -908,7 +883,6 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { layoutItems.push({ description: `${this.Document.LODdisable ? "Enable LOD" : "Disable LOD"}`, event: () => this.Document.LODdisable = !this.Document.LODdisable, icon: "table" }); layoutItems.push({ description: `${this.fitToContent ? "Unset" : "Set"} Fit To Container`, event: () => this.Document.fitToBox = !this.fitToContent, icon: !this.fitToContent ? "expand-arrows-alt" : "compress-arrows-alt" }); layoutItems.push({ description: `${this.Document.useClusters ? "Uncluster" : "Use Clusters"}`, event: () => this.updateClusters(!this.Document.useClusters), icon: "braille" }); - layoutItems.push({ description: `${this.Document.isRuleProvider ? "Stop Auto Format" : "Auto Format"}`, event: this.autoFormat, icon: "chalkboard" }); layoutItems.push({ description: "Arrange contents in grid", event: this.layoutDocsInGrid, icon: "table" }); layoutItems.push({ description: "Analyze Strokes", event: this.analyzeStrokes, icon: "paint-brush" }); layoutItems.push({ description: "Jitter Rotation", event: action(() => this.props.Document.jitterRotation = 10), icon: "paint-brush" }); diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index 614a68e7a..cd78f5d49 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -73,10 +73,8 @@ export class CollectionFreeFormDocumentView extends DocComponent { - const ruleRounding = this.props.ruleProvider ? StrCast(this.props.ruleProvider["ruleRounding_" + this.Document.heading]) : undefined; const ld = this.layoutDoc[StrCast(this.layoutDoc.layoutKey, "layout")] instanceof Doc ? this.layoutDoc[StrCast(this.layoutDoc.layoutKey, "layout")] as Doc : undefined; - const br = StrCast((ld || this.props.Document).borderRounding); - return !br && ruleRounding ? ruleRounding : br; + return StrCast((ld || this.props.Document).borderRounding); } @computed diff --git a/src/client/views/nodes/ContentFittingDocumentView.tsx b/src/client/views/nodes/ContentFittingDocumentView.tsx index e97445f27..96102e0e8 100644 --- a/src/client/views/nodes/ContentFittingDocumentView.tsx +++ b/src/client/views/nodes/ContentFittingDocumentView.tsx @@ -24,7 +24,6 @@ interface ContentFittingDocumentViewProps { fitToBox?: boolean; PanelWidth: () => number; PanelHeight: () => number; - ruleProvider: Doc | undefined; focus?: (doc: Doc) => void; showOverlays?: (doc: Doc) => { title?: string, caption?: string }; CollectionView?: CollectionView; @@ -97,7 +96,6 @@ export class ContentFittingDocumentView extends React.Component(DocB addDocument={this.props.addDocument} moveDocument={this.props.moveDocument} removeDocument={this.props.removeDocument} - ruleProvider={this.props.ruleProvider} addDocTab={this.props.addDocTab} pinToPres={this.props.pinToPres} getTransform={this.getTransform} diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index b491acb8d..2570d232a 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -72,7 +72,6 @@ export interface DocumentViewProps { renderDepth: number; showOverlays?: (doc: Doc) => { title?: string, titleHover?: string, caption?: string }; ContentScaling: () => number; - ruleProvider: Doc | undefined; PanelWidth: () => number; PanelHeight: () => number; focus: (doc: Doc, willZoom: boolean, scale?: number, afterFocus?: () => boolean) => void; @@ -875,7 +874,6 @@ export class DocumentView extends DocComponent(Docu renderDepth={this.props.renderDepth} showOverlays={this.props.showOverlays} ContentScaling={this.childScaling} - ruleProvider={this.props.ruleProvider} PanelWidth={this.props.PanelWidth} PanelHeight={this.props.PanelHeight} focus={this.props.focus} @@ -967,16 +965,14 @@ export class DocumentView extends DocComponent(Docu render() { if (!(this.props.Document instanceof Doc)) return (null); - const ruleColor = this.props.ruleProvider ? StrCast(this.props.ruleProvider["ruleColor_" + this.Document.heading]) : undefined; - const ruleRounding = this.props.ruleProvider ? StrCast(this.props.ruleProvider["ruleRounding_" + this.Document.heading]) : undefined; const colorSet = this.setsLayoutProp("backgroundColor"); const clusterCol = this.props.ContainingCollectionDoc && this.props.ContainingCollectionDoc.clusterOverridesDefaultBackground; const backgroundColor = (clusterCol && !colorSet) ? this.props.backgroundColor(this.Document) || StrCast(this.layoutDoc.backgroundColor) : - ruleColor && !colorSet ? ruleColor : StrCast(this.layoutDoc.backgroundColor) || this.props.backgroundColor(this.Document); + StrCast(this.layoutDoc.backgroundColor) || this.props.backgroundColor(this.Document); const fullDegree = Doc.isBrushedHighlightedDegree(this.props.Document); - const borderRounding = this.getLayoutPropStr("borderRounding") || ruleRounding; + const borderRounding = this.getLayoutPropStr("borderRounding"); const localScale = fullDegree; const animDims = this.Document.animateToDimensions ? Array.from(this.Document.animateToDimensions) : undefined; diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx index 6e6ee1712..538e433a9 100644 --- a/src/client/views/nodes/FieldView.tsx +++ b/src/client/views/nodes/FieldView.tsx @@ -27,7 +27,6 @@ export interface FieldViewProps { fitToBox?: boolean; ContainingCollectionView: Opt; ContainingCollectionDoc: Opt; - ruleProvider: Doc | undefined; Document: Doc; DataDoc?: Doc; LibraryPath: Doc[]; diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index 3814f02da..0a1a79bc4 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -89,7 +89,6 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & private _scrollToRegionReactionDisposer: Opt; private _reactionDisposer: Opt; private _heightReactionDisposer: Opt; - private _rulesReactionDisposer: Opt; private _proxyReactionDisposer: Opt; private _pullReactionDisposer: Opt; private _pushReactionDisposer: Opt; @@ -549,36 +548,6 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & search => search ? this.highlightSearchTerms([Doc.SearchQuery()]) : this.unhighlightSearchTerms(), { fireImmediately: true }); - this._rulesReactionDisposer = reaction(() => { - const ruleProvider = this.props.ruleProvider; - const heading = NumCast(this.layoutDoc.heading); - if (ruleProvider instanceof Doc) { - return { - align: StrCast(ruleProvider["ruleAlign_" + heading], ""), - font: StrCast(ruleProvider["ruleFont_" + heading], "Arial"), - size: NumCast(ruleProvider["ruleSize_" + heading], 13) - }; - } - return undefined; - }, - action((rules: any) => { - this._ruleFontFamily = rules ? rules.font : "Arial"; - this._ruleFontSize = rules ? rules.size : 0; - rules && setTimeout(() => { - const view = this._editorView!; - if (this.ProseRef) { - const n = new NodeSelection(view.state.doc.resolve(0)); - if (this._editorView!.state.doc.textContent === "") { - view.dispatch(view.state.tr.setSelection(new TextSelection(view.state.doc.resolve(0), view.state.doc.resolve(2))). - replaceSelectionWith(this._editorView!.state.schema.nodes.paragraph.create({ align: rules.align }), true)); - } else if (n.node && n.node.type === view.state.schema.nodes.paragraph) { - view.dispatch(view.state.tr.setNodeMarkup(0, n.node.type, { ...n.node.attrs, align: rules.align })); - } - this.tryUpdateHeight(); - } - }, 0); - }), { fireImmediately: true } - ); this._scrollToRegionReactionDisposer = reaction( () => StrCast(this.layoutDoc.scrollToLinkID), async (scrollToLinkID) => { @@ -849,7 +818,6 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & componentWillUnmount() { this._scrollToRegionReactionDisposer && this._scrollToRegionReactionDisposer(); - this._rulesReactionDisposer && this._rulesReactionDisposer(); this._reactionDisposer && this._reactionDisposer(); this._proxyReactionDisposer && this._proxyReactionDisposer(); this._pushReactionDisposer && this._pushReactionDisposer(); @@ -1171,7 +1139,6 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & addDocument={(doc: Doc) => { doc.hideSidebar = true; return this.addDocument(doc); }} CollectionView={undefined} ScreenToLocalTransform={() => this.props.ScreenToLocalTransform().translate(-(this.props.PanelWidth() - this.sidebarWidth), 0)} - ruleProvider={undefined} renderDepth={this.props.renderDepth + 1} ContainingCollectionDoc={this.props.ContainingCollectionDoc} chromeCollapsed={true}> diff --git a/src/client/views/nodes/FormattedTextBoxComment.tsx b/src/client/views/nodes/FormattedTextBoxComment.tsx index f7a530790..8dedfda9b 100644 --- a/src/client/views/nodes/FormattedTextBoxComment.tsx +++ b/src/client/views/nodes/FormattedTextBoxComment.tsx @@ -185,7 +185,6 @@ export class FormattedTextBoxComment { active={returnFalse} addDocument={returnFalse} removeDocument={returnFalse} - ruleProvider={undefined} addDocTab={returnFalse} pinToPres={returnFalse} dontRegisterView={true} diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index db427710e..b7e904283 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -364,7 +364,6 @@ export class ImageBox extends DocAnnotatableComponent diff --git a/src/client/views/nodes/KeyValuePair.tsx b/src/client/views/nodes/KeyValuePair.tsx index 91f8bb3b0..46466aa0f 100644 --- a/src/client/views/nodes/KeyValuePair.tsx +++ b/src/client/views/nodes/KeyValuePair.tsx @@ -58,7 +58,6 @@ export class KeyValuePair extends React.Component { LibraryPath: [], ContainingCollectionView: undefined, ContainingCollectionDoc: undefined, - ruleProvider: undefined, fieldKey: this.props.keyName, isSelected: returnFalse, select: emptyFunction, diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx index 376d27380..52b4f391a 100644 --- a/src/client/views/nodes/VideoBox.tsx +++ b/src/client/views/nodes/VideoBox.tsx @@ -353,7 +353,6 @@ export class VideoBox extends DocAnnotatableComponent diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx index e9118e3ab..f21f9ff46 100644 --- a/src/client/views/nodes/WebBox.tsx +++ b/src/client/views/nodes/WebBox.tsx @@ -211,7 +211,6 @@ export class WebBox extends DocAnnotatableComponent addDocument={this.addDocument} CollectionView={undefined} ScreenToLocalTransform={this.props.ScreenToLocalTransform} - ruleProvider={undefined} renderDepth={this.props.renderDepth + 1} ContainingCollectionDoc={this.props.ContainingCollectionDoc} chromeCollapsed={true}> diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index 62467ce4d..d6829937e 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -650,7 +650,6 @@ export class PDFViewer extends DocAnnotatableComponent diff --git a/src/client/views/presentationview/PresElementBox.tsx b/src/client/views/presentationview/PresElementBox.tsx index c02042380..92dc0f3d2 100644 --- a/src/client/views/presentationview/PresElementBox.tsx +++ b/src/client/views/presentationview/PresElementBox.tsx @@ -175,7 +175,6 @@ export class PresElementBox extends DocComponent(P fitToBox={StrCast(this.targetDoc.type).indexOf(DocumentType.COL) !== -1} addDocument={returnFalse} removeDocument={returnFalse} - ruleProvider={undefined} addDocTab={returnFalse} pinToPres={returnFalse} PanelWidth={() => this.props.PanelWidth() - 20} diff --git a/src/client/views/search/SearchItem.tsx b/src/client/views/search/SearchItem.tsx index 30fcc7908..21a4560cf 100644 --- a/src/client/views/search/SearchItem.tsx +++ b/src/client/views/search/SearchItem.tsx @@ -161,7 +161,6 @@ export class SearchItem extends React.Component { fitToBox={StrCast(this.props.doc.type).indexOf(DocumentType.COL) !== -1} addDocument={returnFalse} removeDocument={returnFalse} - ruleProvider={undefined} addDocTab={returnFalse} pinToPres={returnFalse} getTransform={Transform.Identity} diff --git a/src/mobile/MobileInterface.tsx b/src/mobile/MobileInterface.tsx index ea2fc917f..b1eaeaa0a 100644 --- a/src/mobile/MobileInterface.tsx +++ b/src/mobile/MobileInterface.tsx @@ -38,7 +38,6 @@ export default class MobileInterface extends React.Component { addDocTab={returnFalse} pinToPres={emptyFunction} removeDocument={undefined} - ruleProvider={undefined} onClick={undefined} ScreenToLocalTransform={Transform.Identity} ContentScaling={returnOne} -- cgit v1.2.3-70-g09d2 From 5e67aa8ab95e40730acb584cb5ff812fe470608f Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Mon, 27 Jan 2020 17:32:47 -0500 Subject: template fixes --- src/client/util/DropConverter.ts | 8 +- src/client/util/RichTextRules.ts | 62 +++++++------- src/client/util/RichTextSchema.tsx | 97 +++++++++++++--------- src/client/views/DocComponent.tsx | 4 +- .../views/collections/CollectionCarouselView.tsx | 4 +- src/client/views/nodes/FieldView.tsx | 6 +- src/client/views/nodes/FormattedTextBox.tsx | 2 +- 7 files changed, 104 insertions(+), 79 deletions(-) (limited to 'src/client/views/nodes/FieldView.tsx') diff --git a/src/client/util/DropConverter.ts b/src/client/util/DropConverter.ts index 9c068d2d7..8d92de28f 100644 --- a/src/client/util/DropConverter.ts +++ b/src/client/util/DropConverter.ts @@ -4,7 +4,9 @@ import { DocumentType } from "../documents/DocumentTypes"; import { ObjectField } from "../../new_fields/ObjectField"; import { StrCast } from "../../new_fields/Types"; import { Docs } from "../documents/Documents"; -import { ScriptField } from "../../new_fields/ScriptField"; +import { ScriptField, ComputedField } from "../../new_fields/ScriptField"; +import { RichTextField } from "../../new_fields/RichTextField"; +import { Compute } from "google-auth-library"; export function makeTemplate(doc: Doc): boolean { const layoutDoc = doc.layout instanceof Doc && doc.layout.isTemplateForField ? doc.layout : doc; @@ -18,6 +20,10 @@ export function makeTemplate(doc: Doc): boolean { Doc.MakeMetadataFieldTemplate(d, Doc.GetProto(layoutDoc)); } else if (d.type === DocumentType.COL) { any = makeTemplate(d) || any; + } else if (d.data instanceof RichTextField) { + d._textTemplate = ComputedField.MakeFunction("copyField(this.data)", { this: Doc.name }); + d.isTemplateForField = "data"; + any = true; } }); return any; diff --git a/src/client/util/RichTextRules.ts b/src/client/util/RichTextRules.ts index bc8a0abb1..0de0e21fd 100644 --- a/src/client/util/RichTextRules.ts +++ b/src/client/util/RichTextRules.ts @@ -2,14 +2,15 @@ import { textblockTypeInputRule, smartQuotes, emDash, ellipsis, InputRule } from import { schema } from "./RichTextSchema"; import { wrappingInputRule } from "./prosemirrorPatches"; import { NodeSelection, TextSelection } from "prosemirror-state"; -import { StrCast, Cast } from "../../new_fields/Types"; -import { Doc } from "../../new_fields/Doc"; +import { StrCast, Cast, NumCast } from "../../new_fields/Types"; +import { Doc, DataSym } from "../../new_fields/Doc"; import { FormattedTextBox } from "../views/nodes/FormattedTextBox"; import { Docs, DocUtils } from "../documents/Documents"; import { Id } from "../../new_fields/FieldSymbols"; import { DocServer } from "../DocServer"; import { returnFalse, Utils } from "../../Utils"; import RichTextMenu from "./RichTextMenu"; +import { RichTextField } from "../../new_fields/RichTextField"; export const inpRules = { rules: [ @@ -70,36 +71,26 @@ export const inpRules = { return state.tr.deleteRange(start, end).addStoredMark(schema.marks.pFontSize.create({ fontSize: size })); }), - // make current selection a hyperlink portal (assumes % was used to initiate an EnteringStyle mode) + // create a text display of a metadata field new InputRule( - new RegExp(/!$/), + new RegExp(/\[\[([a-zA-Z_ \-0-9]+)\]\]$/), (state, match, start, end) => { - if (state.selection.to === state.selection.from || !(schema as any).EnteringStyle) return null; - const value = state.doc.textBetween(start, end); - - const node = (state.doc.resolve(start) as any).nodeAfter; - const sm = state.storedMarks || undefined; - const fieldView = state.schema.nodes.dashField.create({ fieldKey: StrCast(value) }); - const replaced = node ? state.tr.replaceRangeWith(start, end, fieldView).setStoredMarks([...node.marks, ...(sm ? sm : [])]) : state.tr; - return replaced.doc.nodeSize > end - 2 ? replaced.setSelection(new TextSelection(replaced.doc.resolve(end - 2))) : replaced; + const fieldKey = match[1]; + const fieldView = state.schema.nodes.dashField.create({ fieldKey: StrCast(fieldKey) }); + return state.tr.deleteRange(start, end).insert(start, fieldView); }), - // make current selection a hyperlink portal (assumes % was used to initiate an EnteringStyle mode) + // create a hyperlink portal new InputRule( - new RegExp(/@$/), + new RegExp(/\[\[:([a-zA-Z_ \-0-9]+)\]\]$/), (state, match, start, end) => { - if (state.selection.to === state.selection.from || !(schema as any).EnteringStyle) return null; - - const value = state.doc.textBetween(start, end); - if (value) { - DocServer.GetRefField(value).then(docx => { - const target = ((docx instanceof Doc) && docx) || Docs.Create.FreeformDocument([], { title: value, _width: 500, _height: 500, }, value); - DocUtils.Publish(target, value, returnFalse, returnFalse); - DocUtils.MakeLink({ doc: (schema as any).Document }, { doc: target }, "portal link", ""); - }); - const link = state.schema.marks.link.create({ href: Utils.prepend("/doc/" + value), location: "onRight", title: value, targetId: value }); - return state.tr.addMark(start, end, link); - } - return state.tr; + const docId = match[1].substring(1); + DocServer.GetRefField(docId).then(docx => { + const target = ((docx instanceof Doc) && docx) || Docs.Create.FreeformDocument([], { title: docId, _width: 500, _height: 500, }, docId); + DocUtils.Publish(target, docId, returnFalse, returnFalse); + DocUtils.MakeLink({ doc: (schema as any).Document }, { doc: target }, "portal link", ""); + }); + const link = state.schema.marks.link.create({ href: Utils.prepend("/doc/" + docId), location: "onRight", title: docId, targetId: docId }); + return state.tr.addMark(start, end, link); }), // stop using active style new InputRule( @@ -209,10 +200,21 @@ export const inpRules = { new InputRule( new RegExp(/%#$/), (state, match, start, end) => { - const target = Docs.Create.TextDocument("", { _width: 75, _height: 35, backgroundColor: "yellow", annotationOn: FormattedTextBox.FocusedBox!.dataDoc, _autoHeight: true, fontSize: 9, title: "inline comment" }); + const textDoc = Doc.GetProto(Cast((schema as any).Document[DataSym], Doc, null)!); + const numInlines = NumCast(textDoc.inlineTextCount); + textDoc.inlineTextCount = numInlines + 1; + const inlineFieldKey = "inline" + numInlines; + const textDocInline = Docs.Create.TextDocument("", { _width: 75, _height: 35, backgroundColor: "yellow", annotationOn: textDoc, _autoHeight: true, fontSize: 9, title: "inline comment" }); + textDocInline.layoutKey = "layout_" + inlineFieldKey; + textDocInline.customTitle = true; + textDocInline.title = "inline"; + textDocInline.isTemplateForField = inlineFieldKey; + textDocInline.proto = textDoc; + textDoc[textDocInline.layoutKey] = FormattedTextBox.LayoutString(inlineFieldKey); + textDoc[inlineFieldKey] = "-inline-"; const node = (state.doc.resolve(start) as any).nodeAfter; - const newNode = schema.nodes.dashComment.create({ docid: target[Id] }); - const dashDoc = schema.nodes.dashDoc.create({ width: 75, height: 35, title: "dashDoc", docid: target[Id], float: "right" }); + const newNode = schema.nodes.dashComment.create({ docid: textDocInline[Id] }); + const dashDoc = schema.nodes.dashDoc.create({ width: 75, height: 35, title: "dashDoc", docid: textDocInline[Id], float: "right" }); const sm = state.storedMarks || undefined; const replaced = node ? state.tr.insert(start, newNode).replaceRangeWith(start + 1, end + 1, dashDoc).insertText(" ", start + 2).setStoredMarks([...node.marks, ...(sm ? sm : [])]) : state.tr; diff --git a/src/client/util/RichTextSchema.tsx b/src/client/util/RichTextSchema.tsx index 21916e3d6..0deedbe39 100644 --- a/src/client/util/RichTextSchema.tsx +++ b/src/client/util/RichTextSchema.tsx @@ -18,6 +18,7 @@ import { Transform } from "./Transform"; import React = require("react"); import { BoolCast, NumCast, StrCast } from "../../new_fields/Types"; import { FormattedTextBox } from "../views/nodes/FormattedTextBox"; +import { ObjectField } from "../../new_fields/ObjectField"; const blockquoteDOM: DOMOutputSpecArray = ["blockquote", 0], hrDOM: DOMOutputSpecArray = ["hr"], preDOM: DOMOutputSpecArray = ["pre", ["code", 0]], brDOM: DOMOutputSpecArray = ["br"], ulDOM: DOMOutputSpecArray = ["ul", 0]; @@ -682,7 +683,7 @@ export class DashDocCommentView { if (target) { const expand = target.hidden; const tr = view.state.tr.setNodeMarkup(target.pos, undefined, { ...target.node.attrs, hidden: target.node.attrs.hidden ? false : true }); - view.dispatch(tr.setSelection(TextSelection.create(tr.doc, getPos() + (expand ? 2 : 1)))); // update the attrs + view.dispatch(tr.setSelection(TextSelection.create(tr.doc, getPos() + (expand ? 2 : 1)))); // update the attrs setTimeout(() => { expand && DocServer.GetRefField(node.attrs.docid).then(async dashDoc => dashDoc instanceof Doc && Doc.linkFollowHighlight(dashDoc)); try { view.dispatch(view.state.tr.setSelection(TextSelection.create(view.state.tr.doc, getPos() + (expand ? 2 : 1)))); } catch (e) { } @@ -734,12 +735,6 @@ export class DashDocView { this._dashSpan.style.height = node.attrs.height; this._dashSpan.style.position = "absolute"; this._dashSpan.style.display = "inline-block"; - const removeDoc = () => { - const pos = getPos(); - const ns = new NodeSelection(view.state.doc.resolve(pos)); - view.dispatch(view.state.tr.setSelection(ns).deleteSelection()); - return true; - }; this._dashSpan.onpointerleave = () => { const ele = document.getElementById("DashDocCommentView-" + node.attrs.docid); if (ele) { @@ -752,46 +747,24 @@ export class DashDocView { (ele as HTMLDivElement).style.backgroundColor = "orange"; } }; + const removeDoc = () => { + const pos = getPos(); + const ns = new NodeSelection(view.state.doc.resolve(pos)); + view.dispatch(view.state.tr.setSelection(ns).deleteSelection()); + return true; + }; DocServer.GetRefField(node.attrs.docid).then(async dashDoc => { if (dashDoc instanceof Doc) { self._dashDoc = dashDoc; dashDoc.hideSidebar = true; - if (node.attrs.width !== dashDoc.width + "px" || node.attrs.height !== dashDoc.height + "px") { + if (node.attrs.width !== dashDoc._width + "px" || node.attrs.height !== dashDoc._height + "px") { try { // bcz: an exception will be thrown if two aliases are open at the same time when a doc view comment is made - view.dispatch(view.state.tr.setNodeMarkup(getPos(), null, { ...node.attrs, width: dashDoc.width + "px", height: dashDoc.height + "px" })); + view.dispatch(view.state.tr.setNodeMarkup(getPos(), null, { ...node.attrs, width: dashDoc._width + "px", height: dashDoc._height + "px" })); } catch (e) { console.log(e); } } - this._reactionDisposer && this._reactionDisposer(); - this._reactionDisposer = reaction(() => dashDoc[HeightSym]() + dashDoc[WidthSym](), () => { - this._dashSpan.style.height = this._outer.style.height = dashDoc[HeightSym]() + "px"; - this._dashSpan.style.width = this._outer.style.width = dashDoc[WidthSym]() + "px"; - }); - ReactDOM.render(, this._dashSpan); + self.doRender(dashDoc, removeDoc); } }); const self = this; @@ -807,6 +780,49 @@ export class DashDocView { this._outer.appendChild(this._dashSpan); (this as any).dom = this._outer; } + doRender(dashDoc: Doc, removeDoc: any) { + const self = this; + const finalLayout = Doc.expandTemplateLayout(dashDoc, this._textBox.dataDoc); + if (!finalLayout) setTimeout(() => self.doRender(dashDoc, removeDoc), 0); + else { + const layoutKey = StrCast(finalLayout.layoutKey); + const finalKey = layoutKey && StrCast(finalLayout[layoutKey]).split("'")?.[1]; + if (finalLayout !== dashDoc && finalKey) { + const finalLayoutField = finalLayout[finalKey] + finalLayoutField instanceof ObjectField && (finalLayout._textTemplate = ObjectField.MakeCopy(finalLayoutField)); + } + this._reactionDisposer && this._reactionDisposer(); + this._reactionDisposer = reaction(() => [finalLayout[WidthSym](), finalLayout[HeightSym]()], (dim) => { + this._dashSpan.style.width = this._outer.style.width = dim[0] + "px"; + this._dashSpan.style.height = this._outer.style.height = dim[1] + "px"; + }, { fireImmediately: true }); + ReactDOM.render(, this._dashSpan); + } + } destroy() { this._reactionDisposer && this._reactionDisposer(); } @@ -837,8 +853,9 @@ export class DashFieldView { this._labelSpan.style.fontWeight = "bold"; this._labelSpan.style.fontSize = "larger"; this._labelSpan.innerHTML = `${node.attrs.fieldKey}: `; + const ddoc = tbox.props.DataDoc || tbox.dataDoc; this._reactionDisposer && this._reactionDisposer(); - this._reactionDisposer = reaction(() => this._textBoxDoc[DataSym][node.attrs.fieldKey], fval => this._fieldSpan.innerHTML = Field.toString(fval as Field), { fireImmediately: true }); + this._reactionDisposer = reaction(() => ddoc[node.attrs.fieldKey], fval => this._fieldSpan.innerHTML = Field.toString(fval as Field), { fireImmediately: true }); this._fieldWrapper.appendChild(this._labelSpan); this._fieldWrapper.appendChild(this._fieldSpan); (this as any).dom = this._fieldWrapper; @@ -1012,7 +1029,7 @@ export class SummaryView { view.dispatch(view.state.tr. setSelection(textSelection). // select the current summarized text (or where it will be if its collapsed) replaceSelection(!visible ? new Slice(Fragment.fromArray([]), 0, 0) : node.attrs.text). // collapse/expand it - setNodeMarkup(getPos(), undefined, attrs)); // update the attrs + setNodeMarkup(getPos(), undefined, attrs)); // update the attrs e.preventDefault(); e.stopPropagation(); this._collapsed.className = this.className(visible); diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx index d98301cf6..a31997a10 100644 --- a/src/client/views/DocComponent.tsx +++ b/src/client/views/DocComponent.tsx @@ -34,7 +34,7 @@ export function DocExtendableComponent

(schemaCt //TODO This might be pretty inefficient if doc isn't observed, because computed doesn't cache then @computed get Document(): T { return schemaCtor(this.props.Document); } @computed get layoutDoc() { return Doc.Layout(this.props.Document); } - @computed get dataDoc() { return (this.props.DataDoc && (this.props.Document.isTemplateForField || this.props.Document.isTemplateDoc) ? this.props.DataDoc : Doc.GetProto(this.props.Document)) as Doc; } + @computed get dataDoc() { return (this.props.DataDoc && (this.props.Document.isTemplateForField || this.props.Document.isTemplateDoc) ? this.props.DataDoc : Cast(this.props.Document.resolvedDataDoc, Doc, null) || Doc.GetProto(this.props.Document)) as Doc; } active = (outsideReaction?: boolean) => !this.props.Document.isBackground && (this.props.Document.forceActive || this.props.isSelected(outsideReaction) || this.props.renderDepth === 0);// && !InkingControl.Instance.selectedTool; // bcz: inking state shouldn't affect static tools } return Component; @@ -57,7 +57,7 @@ export function DocAnnotatableComponent

(schema //TODO This might be pretty inefficient if doc isn't observed, because computed doesn't cache then @computed get Document(): T { return schemaCtor(this.props.Document); } @computed get layoutDoc() { return Doc.Layout(this.props.Document); } - @computed get dataDoc() { return (this.props.DataDoc && (this.props.Document.isTemplateForField || this.props.Document.isTemplateDoc) ? this.props.DataDoc : Doc.GetProto(this.props.Document)) as Doc; } + @computed get dataDoc() { return (this.props.DataDoc && (this.props.Document.isTemplateForField || this.props.Document.isTemplateDoc) ? this.props.DataDoc : Cast(this.props.Document.resolvedDataDoc, Doc, null) || Doc.GetProto(this.props.Document)) as Doc; } _annotationKey: string = "annotations"; public set annotationKey(val: string) { this._annotationKey = val; } diff --git a/src/client/views/collections/CollectionCarouselView.tsx b/src/client/views/collections/CollectionCarouselView.tsx index f2cc2479f..9f32bb0c9 100644 --- a/src/client/views/collections/CollectionCarouselView.tsx +++ b/src/client/views/collections/CollectionCarouselView.tsx @@ -45,13 +45,13 @@ export class CollectionCarouselView extends CollectionSubView(CarouselDocument) Document={this.childLayoutPairs[index].layout} DataDocument={this.childLayoutPairs[index].data} getTransform={this.props.ScreenToLocalTransform} /> -

this.layoutDoc._itemIndex = (index - 1 + this.childLayoutPairs.length) % this.childLayoutPairs.length}> +
{ e.stopPropagation(); this.layoutDoc._itemIndex = (index - 1 + this.childLayoutPairs.length) % this.childLayoutPairs.length }}>
-
this.layoutDoc._itemIndex = (index + 1) % this.childLayoutPairs.length}> +
{ e.stopPropagation(); this.layoutDoc._itemIndex = (index + 1) % this.childLayoutPairs.length }}> { // if (typeof field === "string") { // return

{field}

; // } - else if (field instanceof RichTextField) { - return ; - } + // else if (field instanceof RichTextField) { + // return ; + // } else if (field instanceof ImageField) { return ; } diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index fab267358..5c9f1a754 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -496,7 +496,7 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & this._reactionDisposer = reaction( () => { - const field = this.dataDoc ? Cast(this.dataDoc[this.props.fieldKey], RichTextField) : undefined; + const field = Cast(this.props.Document._textTemplate || this.dataDoc[this.props.fieldKey], RichTextField); return field ? field.Data : RichTextUtils.Initialize(); }, incomingValue => { -- cgit v1.2.3-70-g09d2 From bbaf25c10a3e1fcb36c75d8dedc825a955eab369 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Wed, 29 Jan 2020 23:01:20 -0500 Subject: switched icons over to templates. a bunch of template fixes for working with textboxes as templates. --- src/client/util/DropConverter.ts | 9 +-- src/client/views/DocumentDecorations.tsx | 111 +++++----------------------- src/client/views/nodes/FieldView.tsx | 6 +- src/client/views/nodes/FontIconBox.tsx | 19 ++++- src/client/views/nodes/FormattedTextBox.tsx | 10 ++- 5 files changed, 49 insertions(+), 106 deletions(-) (limited to 'src/client/views/nodes/FieldView.tsx') diff --git a/src/client/util/DropConverter.ts b/src/client/util/DropConverter.ts index 5543edf78..03d8ac953 100644 --- a/src/client/util/DropConverter.ts +++ b/src/client/util/DropConverter.ts @@ -15,16 +15,15 @@ export function makeTemplate(doc: Doc): boolean { let any = false; docs.forEach(d => { if (!StrCast(d.title).startsWith("-")) { - any = true; - Doc.MakeMetadataFieldTemplate(d, Doc.GetProto(layoutDoc)); + any = Doc.MakeMetadataFieldTemplate(d, Doc.GetProto(layoutDoc)) || any; } else if (d.type === DocumentType.COL || d.data instanceof RichTextField) { any = makeTemplate(d) || any; } }); if (layoutDoc[fieldKey] instanceof RichTextField) { - layoutDoc._textTemplate = ComputedField.MakeFunction("copyField(this.data)", { this: Doc.name }); - layoutDoc.isTemplateForField = "data"; - any = true; + if (!StrCast(layoutDoc.title).startsWith("-")) { + any = Doc.MakeMetadataFieldTemplate(layoutDoc, Doc.GetProto(layoutDoc)); + } } return any; } diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 8b0f34bdf..7c4391ec0 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -1,30 +1,25 @@ import { IconProp, library } from '@fortawesome/fontawesome-svg-core'; import { faArrowAltCircleDown, faArrowAltCircleUp, faCheckCircle, faCloudUploadAlt, faLink, faShare, faStopCircle, faSyncAlt, faTag, faTimes } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { action, computed, observable, reaction, runInAction } from "mobx"; +import { action, computed, observable, reaction } from "mobx"; import { observer } from "mobx-react"; -import { Doc, DocListCastAsync } from "../../new_fields/Doc"; +import { Doc } from "../../new_fields/Doc"; import { PositionDocument } from '../../new_fields/documentSchemas'; -import { List } from "../../new_fields/List"; import { ObjectField } from '../../new_fields/ObjectField'; -import { Cast, NumCast, StrCast } from "../../new_fields/Types"; +import { ScriptField } from '../../new_fields/ScriptField'; +import { Cast, StrCast } from "../../new_fields/Types"; import { CurrentUserUtils } from '../../server/authentication/models/current_user_utils'; import { Utils } from "../../Utils"; -import { Docs, DocUtils } from "../documents/Documents"; -import { DocumentManager } from "../util/DocumentManager"; +import { DocUtils } from "../documents/Documents"; +import { DocumentType } from '../documents/DocumentTypes'; import { DragManager } from "../util/DragManager"; import { SelectionManager } from "../util/SelectionManager"; import { undoBatch, UndoManager } from "../util/UndoManager"; -import { MINIMIZED_ICON_SIZE } from "../views/globalCssVariables.scss"; -import { CollectionView } from "./collections/CollectionView"; import { DocumentButtonBar } from './DocumentButtonBar'; import './DocumentDecorations.scss'; import { DocumentView } from "./nodes/DocumentView"; -import { FieldView } from "./nodes/FieldView"; import { IconBox } from "./nodes/IconBox"; import React = require("react"); -import { DocumentType } from '../documents/DocumentTypes'; -import { ScriptField } from '../../new_fields/ScriptField'; const higflyout = require("@hig/flyout"); export const { anchorPoints } = higflyout; export const Flyout = higflyout.default; @@ -51,17 +46,13 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> private _titleHeight = 20; private _downX = 0; private _downY = 0; - private _iconDoc?: Doc = undefined; private _resizeUndo?: UndoManager.Batch; private _radiusDown = [0, 0]; @observable private _accumulatedTitle = ""; - @observable private _minimizedX = 0; - @observable private _minimizedY = 0; @observable private _titleControlString: string = "#title"; @observable private _edtingTitle = false; @observable private _hidden = false; @observable private _opacity = 1; - @observable private _removeIcon = false; @observable public Interacting = false; @observable public pushIcon: IconProp = "arrow-alt-circle-up"; @@ -245,15 +236,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> @action onMinimizeDown = (e: React.PointerEvent): void => { e.stopPropagation(); - this._iconDoc = undefined; if (e.button === 0) { - this._downX = e.pageX; - this._downY = e.pageY; - this._removeIcon = false; - const selDoc = SelectionManager.SelectedDocuments()[0]; - const selDocPos = selDoc.props.ScreenToLocalTransform().scale(selDoc.props.ContentScaling()).inverse().transformPoint(0, 0); - this._minimizedX = selDocPos[0] + 12; - this._minimizedY = selDocPos[1] + 12; document.removeEventListener("pointermove", this.onMinimizeMove); document.addEventListener("pointermove", this.onMinimizeMove); document.removeEventListener("pointerup", this.onMinimizeUp); @@ -266,20 +249,8 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> e.stopPropagation(); if (Math.abs(e.pageX - this._downX) > Utils.DRAG_THRESHOLD || Math.abs(e.pageY - this._downY) > Utils.DRAG_THRESHOLD) { - const selDoc = SelectionManager.SelectedDocuments()[0]; - const selDocPos = selDoc.props.ScreenToLocalTransform().scale(selDoc.props.ContentScaling()).inverse().transformPoint(0, 0); - const snapped = Math.abs(e.pageX - selDocPos[0]) < 20 && Math.abs(e.pageY - selDocPos[1]) < 20; - this._minimizedX = snapped ? selDocPos[0] + 4 : e.clientX; - this._minimizedY = snapped ? selDocPos[1] - 18 : e.clientY; - const selectedDocs = SelectionManager.SelectedDocuments().map(sd => sd); - - if (selectedDocs.length > 1) { - this._iconDoc = this._iconDoc ? this._iconDoc : this.createIcon(SelectionManager.SelectedDocuments(), CollectionView.LayoutString("")); - this.moveIconDoc(this._iconDoc); - } else { - this.getIconDoc(selectedDocs[0]).then(icon => icon && this.moveIconDoc(this._iconDoc = icon)); - } - this._removeIcon = snapped; + document.removeEventListener("pointermove", this.onMinimizeMove); + document.removeEventListener("pointerup", this.onMinimizeUp); } } @undoBatch @@ -290,59 +261,19 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> document.removeEventListener("pointermove", this.onMinimizeMove); document.removeEventListener("pointerup", this.onMinimizeUp); const selectedDocs = SelectionManager.SelectedDocuments().map(sd => sd); - if (this._iconDoc && selectedDocs.length === 1 && this._removeIcon) { - selectedDocs[0].props.removeDocument && selectedDocs[0].props.removeDocument(this._iconDoc); - } - if (!this._removeIcon && selectedDocs.length === 1) { // if you click on the top-left button when just 1 doc is selected, then collapse it. not sure why we don't do it for multiple selections - this.getIconDoc(selectedDocs[0]).then(async icon => { - const minimizedDoc = await Cast(selectedDocs[0].props.Document.minimizedDoc, Doc); - if (minimizedDoc) { - const scrpt = selectedDocs[0].props.ScreenToLocalTransform().scale(selectedDocs[0].props.ContentScaling()).inverse().transformPoint( - NumCast(minimizedDoc.x) - NumCast(selectedDocs[0].Document.x), NumCast(minimizedDoc.y) - NumCast(selectedDocs[0].Document.y)); - SelectionManager.DeselectAll(); - DocumentManager.Instance.animateBetweenPoint(scrpt, await DocListCastAsync(minimizedDoc.maximizedDocs)); - } - }); - } - this._removeIcon = false; - } - runInAction(() => this._minimizedX = this._minimizedY = 0); - } - - @undoBatch - @action createIcon = (selected: DocumentView[], layoutString: string): Doc => { - const doc = selected[0].props.Document; - const iconDoc = Docs.Create.IconDocument(layoutString); - iconDoc.isButton = true; - - IconBox.AutomaticTitle(iconDoc); - //iconDoc.proto![this._fieldKey] = selected.length > 1 ? "collection" : undefined; - iconDoc._width = Number(MINIMIZED_ICON_SIZE); - iconDoc._height = Number(MINIMIZED_ICON_SIZE); - iconDoc.x = NumCast(doc.x); - iconDoc.y = NumCast(doc.y) - 24; - iconDoc.maximizedDocs = new List(selected.map(s => s.props.Document)); - selected.length === 1 && (doc.minimizedDoc = iconDoc); - selected[0].props.addDocument && selected[0].props.addDocument(iconDoc); - return iconDoc; - } - @action - public getIconDoc = async (docView: DocumentView): Promise => { - const doc = docView.props.Document; - let iconDoc: Doc | undefined = await Cast(doc.minimizedDoc, Doc); - - if (!iconDoc || !DocumentManager.Instance.getDocumentView(iconDoc)) { - const layout = StrCast(doc.layout, FieldView.LayoutString(DocumentView, "")); - iconDoc = this.createIcon([docView], layout); + selectedDocs.map(dv => { + const layoutKey = Cast(dv.props.Document.layoutKey, "string", null); + const collapse = layoutKey !== "layout_icon"; + if (collapse) { + if (layoutKey) dv.props.Document.deiconifyLayout = layoutKey.replace("layout_", ""); + dv.setCustomView(collapse, "icon"); + } else { + const deiconifyLayout = Cast(dv.props.Document.deiconifyLayout, "string", null); + dv.setCustomView(deiconifyLayout ? true : false, deiconifyLayout); + dv.props.Document.deiconifyLayout = undefined; + } + }); } - return iconDoc; - } - moveIconDoc(iconDoc: Doc) { - const selView = SelectionManager.SelectedDocuments()[0]; - const where = (selView.props.ScreenToLocalTransform()).scale(selView.props.ContentScaling()). - transformPoint(this._minimizedX - 12, this._minimizedY - 12); - iconDoc.x = where[0] + NumCast(selView.props.Document.x); - iconDoc.y = where[1] + NumCast(selView.props.Document.y); } @action @@ -578,8 +509,6 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> }}> {minimizeIcon} - {/* */} - {this._edtingTitle ? this.titleBlur(true)} onChange={this.titleChanged} onKeyPress={this.titleEntered} /> :
{`${this.selectionTitle}`}
} diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx index 4904ee5c3..dbbb76f83 100644 --- a/src/client/views/nodes/FieldView.tsx +++ b/src/client/views/nodes/FieldView.tsx @@ -72,9 +72,9 @@ export class FieldView extends React.Component { // else if (field instanceof RichTextField) { // return ; // } - else if (field instanceof ImageField) { - return ; - } + // else if (field instanceof ImageField) { + // return ; + // } // else if (field instaceof PresBox) { // return ; // } diff --git a/src/client/views/nodes/FontIconBox.tsx b/src/client/views/nodes/FontIconBox.tsx index 2433251b3..a191ac4f4 100644 --- a/src/client/views/nodes/FontIconBox.tsx +++ b/src/client/views/nodes/FontIconBox.tsx @@ -5,10 +5,11 @@ import { createSchema, makeInterface } from '../../../new_fields/Schema'; import { DocComponent } from '../DocComponent'; import './FontIconBox.scss'; import { FieldView, FieldViewProps } from './FieldView'; -import { StrCast } from '../../../new_fields/Types'; +import { StrCast, Cast } from '../../../new_fields/Types'; import { Utils } from "../../../Utils"; import { runInAction, observable, reaction, IReactionDisposer } from 'mobx'; import { Doc } from '../../../new_fields/Doc'; +import { ContextMenu } from '../ContextMenu'; const FontIconSchema = createSchema({ icon: "string" }); @@ -32,13 +33,25 @@ export class FontIconBox extends DocComponent( } }, { fireImmediately: true }); } + + showTemplate = (): void => { + const dragFactory = Cast(this.props.Document.dragFactory, Doc, null); + dragFactory && this.props.addDocTab(dragFactory, undefined, "onRight"); + } + + specificContextMenu = (): void => { + const cm = ContextMenu.Instance; + cm.addItem({ description: "Show Template", event: this.showTemplate, icon: "tag" }); + } + componentWillUnmount() { - this._backgroundReaction && this._backgroundReaction(); + this._backgroundReaction?.(); } + render() { const referenceDoc = (this.props.Document.dragFactory instanceof Doc ? this.props.Document.dragFactory : this.props.Document); const referenceLayout = Doc.Layout(referenceDoc); - return