diff options
-rw-r--r-- | src/client/documents/Documents.ts | 40 | ||||
-rw-r--r-- | src/client/goldenLayout.js | 2 | ||||
-rw-r--r-- | src/client/util/CurrentUserUtils.ts | 44 | ||||
-rw-r--r-- | src/client/util/DragManager.ts | 54 | ||||
-rw-r--r-- | src/client/views/MainView.tsx | 6 | ||||
-rw-r--r-- | src/client/views/collections/CollectionMenu.tsx | 4 | ||||
-rw-r--r-- | src/client/views/collections/CollectionPileView.tsx | 3 | ||||
-rw-r--r-- | src/client/views/collections/CollectionTreeView.tsx | 16 | ||||
-rw-r--r-- | src/client/views/collections/TreeView.tsx | 4 | ||||
-rw-r--r-- | src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx | 2 | ||||
-rw-r--r-- | src/client/views/collections/collectionFreeForm/MarqueeView.tsx | 9 | ||||
-rw-r--r-- | src/client/views/collections/collectionSchema/CollectionSchemaView.tsx | 4 | ||||
-rw-r--r-- | src/client/views/collections/collectionSchema/SchemaTableCell.tsx | 7 | ||||
-rw-r--r-- | src/client/views/nodes/DocumentView.tsx | 2 | ||||
-rw-r--r-- | src/client/views/nodes/trails/PresBox.tsx | 5 | ||||
-rw-r--r-- | src/client/views/topbar/TopBar.tsx | 3 | ||||
-rw-r--r-- | src/fields/documentSchemas.ts | 6 |
17 files changed, 129 insertions, 82 deletions
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 2d2f5fe4a..8a13395c3 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -68,10 +68,20 @@ class EmptyBox { return ''; } } + +export enum FInfoFieldType { + string, + boolean, + number, + Doc, + enumeration, + date, + list, +} export class FInfo { description: string = ''; readOnly: boolean = false; - fieldType?: string = ''; + fieldType?: FInfoFieldType; values?: Field[]; filterable?: boolean = true; @@ -84,7 +94,7 @@ export class FInfo { searchable = () => true; } class BoolInfo extends FInfo { - fieldType? = 'boolean'; + fieldType? = FInfoFieldType.boolean; values?: boolean[] = [true, false]; constructor(d: string, filterable?: boolean) { super(d); @@ -93,7 +103,7 @@ class BoolInfo extends FInfo { override searchable = () => false; } class NumInfo extends FInfo { - fieldType? = 'number'; + fieldType? = FInfoFieldType.number; values?: number[] = []; constructor(d: string, filterable?: boolean, readOnly?: boolean, values?: number[]) { super(d, readOnly); @@ -103,7 +113,7 @@ class NumInfo extends FInfo { override searchable = () => false; } class StrInfo extends FInfo { - fieldType? = 'string'; + fieldType? = FInfoFieldType.string; values?: string[] = []; constructor(d: string, filterable?: boolean, readOnly?: boolean, values?: string[]) { super(d, readOnly); @@ -112,7 +122,7 @@ class StrInfo extends FInfo { } } class DocInfo extends FInfo { - fieldType? = 'Doc'; + fieldType? = FInfoFieldType.Doc; values?: Doc[] = []; constructor(d: string, filterable?: boolean, values?: Doc[]) { super(d, true); @@ -122,45 +132,45 @@ class DocInfo extends FInfo { override searchable = () => false; } class DimInfo extends FInfo { - fieldType? = 'enumeration'; + fieldType? = FInfoFieldType.enumeration; values? = [DimUnit.Pixel, DimUnit.Ratio]; readOnly = false; filterable = false; override searchable = () => false; } class PEInfo extends FInfo { - fieldType? = 'enumeration'; + fieldType? = FInfoFieldType.enumeration; values? = ['all', 'none']; readOnly = false; filterable = false; override searchable = () => false; } class DAInfo extends FInfo { - fieldType? = 'enumeration'; - values? = ['embed', 'copy', 'move', 'same', 'proto', 'none']; + fieldType? = FInfoFieldType.enumeration; + values? = ['embed', 'copy', 'move', 'same', 'add', 'inSame', 'proto']; readOnly = false; filterable = false; override searchable = () => false; } class CTypeInfo extends FInfo { - fieldType? = 'enumeration'; + fieldType? = FInfoFieldType.enumeration; values? = Array.from(Object.keys(CollectionViewType)); readOnly = false; filterable = false; override searchable = () => false; } class DTypeInfo extends FInfo { - fieldType? = 'enumeration'; + fieldType? = FInfoFieldType.enumeration; values? = Array.from(Object.keys(DocumentType)); override searchable = () => false; } class DateInfo extends FInfo { - fieldType? = 'date'; + fieldType? = FInfoFieldType.date; values?: DateField[] = []; filterable = true; } class ListInfo extends FInfo { - fieldType? = 'list'; + fieldType? = FInfoFieldType.list; values?: List<any>[] = []; } type BOOLt = BoolInfo | boolean; @@ -728,7 +738,7 @@ export namespace Docs { { data: '', layout: { view: ComparisonBox, dataField: defaultDataKey }, - options: { backgroundColor: 'gray', dropAction: 'move', waitForDoubleClickToClick: 'always', layout_reflowHorizontal: true, layout_reflowVertical: true, layout_nativeDimEditable: true, systemIcon: 'BsLayoutSplit' }, + options: { backgroundColor: 'gray', dropAction: dropActionType.move, waitForDoubleClickToClick: 'always', layout_reflowHorizontal: true, layout_reflowVertical: true, layout_nativeDimEditable: true, systemIcon: 'BsLayoutSplit' }, }, ], [ @@ -1182,7 +1192,7 @@ export namespace Docs { return InstanceFromProto( Prototypes.get(DocumentType.COL), new List(documents), - { backgroundColor: 'transparent', dropAction: 'move', _forceActive: true, _freeform_noZoom: true, _freeform_noAutoPan: true, ...options, _type_collection: CollectionViewType.Pile }, + { backgroundColor: 'transparent', dropAction: dropActionType.move, _forceActive: true, _freeform_noZoom: true, _freeform_noAutoPan: true, ...options, _type_collection: CollectionViewType.Pile }, id ); } diff --git a/src/client/goldenLayout.js b/src/client/goldenLayout.js index 2b94d35ee..cb1dfd76a 100644 --- a/src/client/goldenLayout.js +++ b/src/client/goldenLayout.js @@ -4727,7 +4727,7 @@ */ } else { type = isVertical ? 'column' : 'row'; - if (this.parent.contentItems.length === 1) { + if (this.parent.contentItems.length === 1 && this.contentItems.length === 1) { let grandparent = this.parent.parent; let correctRowOrCol = this.layoutManager.createContentItem({ type: type }, this); grandparent.replaceChild(this.parent, correctRowOrCol); diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 714e33d25..d396ba815 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -14,7 +14,7 @@ import { SetCachedGroups, SharingPermissions } from "../../fields/util"; import { GestureUtils } from "../../pen-gestures/GestureUtils"; import { DocServer } from "../DocServer"; import { CollectionViewType, DocumentType } from "../documents/DocumentTypes"; -import { DocUtils, Docs, DocumentOptions, FInfo } from "../documents/Documents"; +import { DocUtils, Docs, DocumentOptions, FInfo, FInfoFieldType } from "../documents/Documents"; import { DashboardView } from "../views/DashboardView"; import { OverlayView } from "../views/OverlayView"; import { CollectionTreeView, TreeViewType } from "../views/collections/CollectionTreeView"; @@ -257,11 +257,11 @@ export class CurrentUserUtils { {key: "DataViz", creator: opts => Docs.Create.DataVizDocument("/users/rz/Downloads/addresses.csv", opts), opts: { _width: 300, _height: 300 }}, {key: "Header", creator: headerTemplate, opts: { _width: 300, _height: 70, _headerPointerEvents: "all", _headerHeight: 12, _headerFontSize: 9, _layout_autoHeight: true, treeView_HideUnrendered: true}}, {key: "ViewSlide", creator: slideView, opts: { _width: 400, _height: 300, _xMargin: 3, _yMargin: 3,}}, - {key: "Trail", creator: Docs.Create.PresDocument, opts: { _width: 400, _height: 30, _type_collection: CollectionViewType.Stacking, dropAction: "embed" as dropActionType, treeView_HideTitle: true, _layout_fitWidth:true, layout_boxShadow: "0 0" }}, + {key: "Trail", creator: Docs.Create.PresDocument, opts: { _width: 400, _height: 30, _type_collection: CollectionViewType.Stacking, dropAction: dropActionType.embed, treeView_HideTitle: true, _layout_fitWidth:true, layout_boxShadow: "0 0" }}, {key: "Tab", creator: opts => Docs.Create.FreeformDocument([], opts), opts: { _width: 500, _height: 800, _layout_fitWidth: true, _freeform_backgroundGrid: true, }}, {key: "Slide", creator: opts => Docs.Create.TreeDocument([], opts), opts: { _width: 300, _height: 200, _type_collection: CollectionViewType.Tree, treeView_HasOverlay: true, _text_fontSize: "20px", _layout_autoHeight: true, - dropAction:'move', treeView_Type: TreeViewType.outline, + dropAction:dropActionType.move, treeView_Type: TreeViewType.outline, backgroundColor: "white", _xMargin: 0, _yMargin: 0, _createDocOnCR: true }, funcs: {title: 'this.text?.Text'}}, ]; @@ -311,7 +311,7 @@ export class CurrentUserUtils { const reqdOpts:DocumentOptions = { title: "Document Creators", _layout_showTitle: "title", _xMargin: 0, _dragOnlyWithinContainer: true, _layout_hideContextMenu: true, _chromeHidden: true, isSystem: true, _layout_autoHeight: true, _width: 500, _height: 300, _layout_fitWidth: true, _columnWidth: 40, ignoreClick: true, _lockedPosition: true, _forceActive: true, - childDragAction: 'embed' + childDragAction: dropActionType.embed }; const reqdScripts = { dropConverter: "convertToButtons(dragData)" }; return DocUtils.AssignScripts(DocUtils.AssignOpts(dragCreatorDoc, reqdOpts, creatorBtns) ?? Docs.Create.MasonryDocument(creatorBtns, reqdOpts), reqdScripts); @@ -353,7 +353,7 @@ export class CurrentUserUtils { }); const reqdStackOpts:DocumentOptions ={ - title: "menuItemPanel", childDragAction: "same", layout_boxShadow: "rgba(0,0,0,0)", dontRegisterView: true, ignoreClick: true, + title: "menuItemPanel", childDragAction: dropActionType.same, layout_boxShadow: "rgba(0,0,0,0)", dontRegisterView: true, ignoreClick: true, _chromeHidden: true, _gridGap: 0, _yMargin: 0, _xMargin: 0, _layout_autoHeight: false, _width: 60, _columnWidth: 60, _lockedPosition: true, isSystem: true, }; return DocUtils.AssignDocField(doc, field, (opts, items) => Docs.Create.StackingDocument(items??[], opts), reqdStackOpts, menuBtns, { dropConverter: "convertToButtons(dragData)" }); @@ -436,7 +436,7 @@ export class CurrentUserUtils { /// Search option on the left side button panel static setupSearcher(doc: Doc, field:string) { return DocUtils.AssignDocField(doc, field, (opts, items) => Docs.Create.SearchDocument(opts), { - dontRegisterView: true, backgroundColor: "dimgray", ignoreClick: true, title: "Search Panel", isSystem: true, childDragAction: "embed", + dontRegisterView: true, backgroundColor: "dimgray", ignoreClick: true, title: "Search Panel", isSystem: true, childDragAction: dropActionType.embed, _lockedPosition: true, _type_collection: CollectionViewType.Schema }); } @@ -476,8 +476,8 @@ export class CurrentUserUtils { const childContextMenuIcons = ["tv", "camera", "users", "times", "trash"]; // entries must be kept in synch with childContextMenuScripts, childContextMenuLabels, and childContextMenuFilters const reqdOpts:DocumentOptions = { title: "My Dashboards", childHideLinkButton: true, treeView_FreezeChildren: "remove|add", treeView_HideTitle: true, layout_boxShadow: "0 0", childDontRegisterViews: true, - dropAction: "inSame", treeView_Type: TreeViewType.fileSystem, isFolder: true, isSystem: true, treeView_TruncateTitleWidth: 350, ignoreClick: true, - layout_headerButton: newDashboardButton, childDragAction: "inSame", + dropAction: dropActionType.inPlace, treeView_Type: TreeViewType.fileSystem, isFolder: true, isSystem: true, treeView_TruncateTitleWidth: 350, ignoreClick: true, + layout_headerButton: newDashboardButton, childDragAction: dropActionType.inPlace, _layout_showTitle: "title", _height: 400, _gridGap: 5, _forceActive: true, _lockedPosition: true, contextMenuLabels:new List<string>(contextMenuLabels), contextMenuIcons:new List<string>(contextMenuIcons), @@ -510,9 +510,9 @@ export class CurrentUserUtils { const newFolderButton = DocUtils.AssignScripts(DocUtils.AssignOpts(DocCast(myFilesystem?.layout_headerButton), newFolderOpts) ?? Docs.Create.FontIconDocument(newFolderOpts), newFolderScript); const reqdOpts:DocumentOptions = { _layout_showTitle: "title", _height: 100, _forceActive: true, - title: "My Documents", layout_headerButton: newFolderButton, treeView_HideTitle: true, dropAction: 'add', isSystem: true, + title: "My Documents", layout_headerButton: newFolderButton, treeView_HideTitle: true, dropAction: dropActionType.add, isSystem: true, isFolder: true, treeView_Type: TreeViewType.fileSystem, childHideLinkButton: true, layout_boxShadow: "0 0", childDontRegisterViews: true, - treeView_TruncateTitleWidth: 350, ignoreClick: true, childDragAction: "embed", + treeView_TruncateTitleWidth: 350, ignoreClick: true, childDragAction: dropActionType.embed, layout_explainer: "This is your file manager where you can create folders to keep track of documents independently of your dashboard." }; const fileFolders = new Set(DocListCast(DocCast(doc[field])?.data)); @@ -522,8 +522,8 @@ export class CurrentUserUtils { /// initializes the panel displaying docs that have been recently closed static setupRecentlyClosed(doc: Doc, field:string) { const reqdOpts:DocumentOptions = { _layout_showTitle: "title", _lockedPosition: true, _gridGap: 5, _forceActive: true, isFolder: true, - title: "My Recently Closed", childHideLinkButton: true, treeView_HideTitle: true, childDragAction: "move", isSystem: true, - treeView_TruncateTitleWidth: 350, ignoreClick: true, layout_boxShadow: "0 0", childDontRegisterViews: true, dropAction: "same", + title: "My Recently Closed", childHideLinkButton: true, treeView_HideTitle: true, childDragAction: dropActionType.move, isSystem: true, + treeView_TruncateTitleWidth: 350, ignoreClick: true, layout_boxShadow: "0 0", childDontRegisterViews: true, dropAction: dropActionType.same, contextMenuLabels: new List<string>(["Empty recently closed"]), contextMenuIcons:new List<string>(["trash"]), layout_explainer: "Recently closed documents appear in this menu. They will only be deleted if you explicity empty this list." @@ -546,7 +546,7 @@ export class CurrentUserUtils { static setupUserDocView(doc: Doc, field:string) { const reqdOpts:DocumentOptions = { _lockedPosition: true, _gridGap: 5, _forceActive: true, title: Doc.CurrentUserEmail +"-view", - layout_boxShadow: "0 0", childDontRegisterViews: true, dropAction: "same", ignoreClick: true, isSystem: true, + layout_boxShadow: "0 0", childDontRegisterViews: true, dropAction: dropActionType.same, ignoreClick: true, isSystem: true, treeView_HideTitle: true, treeView_TruncateTitleWidth: 350 }; if (!doc[field]) DocUtils.AssignOpts(doc, {treeView_Open: true, treeView_ExpandedView: "fields" }); @@ -587,7 +587,7 @@ export class CurrentUserUtils { ]; const btns = btnDescs.map(desc => dockBtn({_width: 30, _height: 30, defaultDoubleClick: 'ignore', undoIgnoreFields: new List<string>(['opacity']), _dragOnlyWithinContainer: true, ...desc.opts}, desc.scripts)); const dockBtnsReqdOpts:DocumentOptions = { - title: "docked buttons", _height: 40, flexGap: 0, layout_boxShadow: "standard", childDragAction: 'move', + title: "docked buttons", _height: 40, flexGap: 0, layout_boxShadow: "standard", childDragAction: dropActionType.move, childDontRegisterViews: true, linearView_IsOpen: true, linearView_Expandable: true, ignoreClick: true }; reaction(() => UndoManager.redoStack.slice(), () => Doc.GetProto(btns.find(btn => btn.title === "Redo")!).opacity = UndoManager.CanRedo() ? 1 : 0.4, { fireImmediately: true }); @@ -743,7 +743,7 @@ export class CurrentUserUtils { /// Initializes all the default buttons for the top bar context menu static setupContextMenuButtons(doc: Doc, field="myContextMenuBtns") { - const reqdCtxtOpts:DocumentOptions = { title: "context menu buttons", undoIgnoreFields:new List<string>(['width', "linearView_IsOpen"]), flexGap: 0, childDragAction: 'embed', childDontRegisterViews: true, linearView_IsOpen: true, ignoreClick: true, linearView_Expandable: false, _height: 35 }; + const reqdCtxtOpts:DocumentOptions = { title: "context menu buttons", undoIgnoreFields:new List<string>(['width', "linearView_IsOpen"]), flexGap: 0, childDragAction: dropActionType.embed, childDontRegisterViews: true, linearView_IsOpen: true, ignoreClick: true, linearView_Expandable: false, _height: 35 }; const ctxtMenuBtnsDoc = DocUtils.AssignDocField(doc, field, (opts, items) => this.linearButtonList(opts, items??[]), reqdCtxtOpts, undefined); const ctxtMenuBtns = CurrentUserUtils.contextMenuTools().map(params => this.setupContextMenuBtn(params, ctxtMenuBtnsDoc) ); return DocUtils.AssignOpts(ctxtMenuBtnsDoc, reqdCtxtOpts, ctxtMenuBtns); @@ -769,7 +769,7 @@ export class CurrentUserUtils { ]; const btns = btnDescs.map(desc => dockBtn({_width: desc.opts.width??30, _height: 30, defaultDoubleClick: 'ignore', undoIgnoreFields: new List<string>(['opacity']), _dragOnlyWithinContainer: true, ...desc.opts}, desc.scripts, desc.funcs)); const dockBtnsReqdOpts:DocumentOptions = { - title: "docked buttons", _height: 40, flexGap: 0, layout_boxShadow: "standard", childDragAction: 'move', + title: "docked buttons", _height: 40, flexGap: 0, layout_boxShadow: "standard", childDragAction: dropActionType.move, childDontRegisterViews: true, linearView_IsOpen: true, linearView_Expandable: false, ignoreClick: true }; return DocUtils.AssignDocField(doc, field, (opts, items) => this.linearButtonList(opts, items??[]), dockBtnsReqdOpts, btns); @@ -809,7 +809,7 @@ export class CurrentUserUtils { // childContextMenuLabels: new List<string>(["Add to Dashboards",]), // childContextMenuIcons: new List<string>(["user-plus",]), "acl-Guest": SharingPermissions.Augment, "_acl-Guest": SharingPermissions.Augment, - childDragAction: "embed", isSystem: true, childContentPointerEvents: "none", childLimitHeight: 0, _yMargin: 0, _gridGap: 15, childDontRegisterViews:true, + childDragAction: dropActionType.embed, isSystem: true, childContentPointerEvents: "none", childLimitHeight: 0, _yMargin: 0, _gridGap: 15, childDontRegisterViews:true, // NOTE: treeView_HideTitle & _layout_showTitle is for a TreeView's editable title, _layout_showTitle is for DocumentViews title bar _layout_showTitle: "title", treeView_HideTitle: true, ignoreClick: true, _lockedPosition: true, layout_boxShadow: "0 0", _chromeHidden: true, dontRegisterView: true, layout_explainer: "This is where documents or dashboards that other users have shared with you will appear. To share a document or dashboard right click and select 'Share'" @@ -824,7 +824,7 @@ export class CurrentUserUtils { const reqdOpts:DocumentOptions = { title: "My Imports", _forceActive: true, _layout_showTitle: "title", childLayoutString: ImportElementBox.LayoutString('data'), _dragOnlyWithinContainer: true, _layout_hideContextMenu: true, childLimitHeight: 0, onClickScriptDisable:"never", - childDragAction: "copy", _layout_autoHeight: true, _yMargin: 50, _gridGap: 15, layout_boxShadow: "0 0", _lockedPosition: true, isSystem: true, _chromeHidden: true, + childDragAction: dropActionType.copy, _layout_autoHeight: true, _yMargin: 50, _gridGap: 15, layout_boxShadow: "0 0", _lockedPosition: true, isSystem: true, _chromeHidden: true, dontRegisterView: true, layout_explainer: "This is where documents that are Imported into Dash will go." }; const myImports = DocUtils.AssignDocField(doc, field, (opts) => Docs.Create.MasonryDocument([], opts), reqdOpts, undefined, {onClick: "deselectAll()"}); @@ -886,7 +886,7 @@ export class CurrentUserUtils { this.setupDocTemplates(doc); // sets up the template menu of templates //this.setupFieldInfos(doc); // sets up the collection of field info descriptions for each possible DocumentOption DocUtils.AssignDocField(doc, "globalScriptDatabase", (opts) => Docs.Prototypes.MainScriptDocument(), {}); - DocUtils.AssignDocField(doc, "myHeaderBar", (opts) => Docs.Create.MulticolumnDocument([], opts), { title: "My Header Bar", isSystem: true, _chromeHidden:true, childLayoutFitWidth:false, childDocumentsActive:false, dropAction: 'move'}); // drop down panel at top of dashboard for stashing documents + DocUtils.AssignDocField(doc, "myHeaderBar", (opts) => Docs.Create.MulticolumnDocument([], opts), { title: "My Header Bar", isSystem: true, _chromeHidden:true, childLayoutFitWidth:false, childDocumentsActive:false, dropAction: dropActionType.move}); // drop down panel at top of dashboard for stashing documents Doc.AddDocToList(Doc.MyFilesystem, undefined, Doc.MyDashboards) Doc.AddDocToList(Doc.MyFilesystem, undefined, Doc.MySharedDocs) @@ -909,9 +909,9 @@ export class CurrentUserUtils { const options = pair[1] as FInfo; const opts:DocumentOptions = { isSystem: true, title: pair[0], ...OmitKeys(options, ["values"]).omit, fieldIsLayout: pair[0].startsWith("_")}; switch (options.fieldType) { - case "boolean": opts.fieldValues = new List<boolean>(options.values as any); break; - case "number": opts.fieldValues = new List<number>(options.values as any); break; - case Doc.name: opts.fieldValues = new List<Doc>(options.values as any); break; + case FInfoFieldType.boolean: opts.fieldValues = new List<boolean>(options.values as any); break; + case FInfoFieldType.number: opts.fieldValues = new List<number>(options.values as any); break; + case FInfoFieldType.Doc: opts.fieldValues = new List<Doc>(options.values as any); break; default: opts.fieldValues = new List<string>(options.values as any); break;// string, pointerEvents, dimUnit, dropActionType } DocUtils.AssignDocField(infos, pair[0], opts => Doc.assign(new Doc(), OmitKeys(opts,["values"]).omit), opts); diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 1f093a33c..f6af6196f 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -1,10 +1,24 @@ +/** + * The DragManager handles all dragging interactions that occur entirely within Dash (as opposed to external drag operations from the file system, etc) + * + * Events are generated for + * a pause in the drag movement (dashDragMovePause) as a Doc(s) is dragged, + * just before (dashPreDrop) a Doc(s) is dropped, + * and just after (dashDropEvent) a Doc(s) is dropped + * If the document is dragged and paused over the golden layout header tabs, the + * drag interaction will switch to a golden layout tab drag. + * + * All drag operations can be aborted by hitting the Esc key + * + */ + import { action, observable, runInAction } from 'mobx'; import { DateField } from '../../fields/DateField'; import { Doc, Field, Opt, StrListCast } from '../../fields/Doc'; import { List } from '../../fields/List'; import { PrefetchProxy } from '../../fields/Proxy'; import { ScriptField } from '../../fields/ScriptField'; -import { ScriptCast, StrCast } from '../../fields/Types'; +import { ScriptCast } from '../../fields/Types'; import { emptyFunction, Utils } from '../../Utils'; import { Docs, DocUtils } from '../documents/Documents'; import { CollectionFreeFormDocumentView } from '../views/nodes/CollectionFreeFormDocumentView'; @@ -16,7 +30,15 @@ import { UndoManager } from './UndoManager'; import { DocData } from '../../fields/DocSymbols'; const { default : { contextMenuZindex } } = require('../views/global/globalCssVariables.module.scss'); // prettier-ignore -export type dropActionType = 'embed' | 'copy' | 'move' | 'add' | 'same' | 'inSame' | 'proto' | 'none' | undefined; // undefined = move, "same" = move but don't call dropPropertiesToRemove +export enum dropActionType { + embed = 'embed', // create a new embedding of the dragged document for the new location + copy = 'copy', // copy the dragged document + move = 'move', // move the dragged document to the drop location after removing it from where it was + add = 'add', // add the dragged document to the drop location without removing it from where it was + same = 'same', // only allow drop within same collection (or same hierarchical tree collection) + inPlace = 'inSame', // keep document in place (unless overridden by a drag modifier) + proto = 'proto', +} // undefined = move, same = move but doesn't call dropPropertiesToRemove /** * Initialize drag @@ -129,9 +151,9 @@ export namespace DragManager { treeViewDoc?: Doc; offset: number[]; canEmbed?: boolean; - userDropAction: dropActionType; // the user requested drop action -- this will be honored as specified by modifier keys + userDropAction?: dropActionType; // the user requested drop action -- this will be honored as specified by modifier keys defaultDropAction?: dropActionType; // an optionally specified default drop action when there is no user drop actionl - this will be honored if there is no user drop action - dropAction: dropActionType; // a drop action request by the initiating code. the actual drop action may be different -- eg, if the request is 'embed', but the document is dropped within the same collection, the drop action will be switched to 'move' + dropAction?: dropActionType; // a drop action request by the initiating code. the actual drop action may be different -- eg, if the request is 'embed', but the document is dropped within the same collection, the drop action will be switched to 'move' dropPropertiesToRemove?: string[]; moveDocument?: MoveFunction; removeDocument?: RemoveFunction; @@ -170,8 +192,8 @@ export namespace DragManager { dropDocCreator: (annotationOn: Doc | undefined) => Doc; dropDocument?: Doc; offset: number[]; - dropAction: dropActionType; - userDropAction: dropActionType; + dropAction?: dropActionType; + userDropAction?: dropActionType; } let defaultPreDropFunc = (e: Event, de: DragManager.DropEvent, targetAction: dropActionType) => { @@ -189,7 +211,7 @@ export namespace DragManager { const handler = (e: Event) => dropFunc(e, (e as CustomEvent<DropEvent>).detail); const preDropHandler = (e: Event) => { const de = (e as CustomEvent<DropEvent>).detail; - (preDropFunc ?? defaultPreDropFunc)(e, de, StrCast(doc.dropAction) as dropActionType); + (preDropFunc ?? defaultPreDropFunc)(e, de, doc.dropAction as any as dropActionType); }; element.addEventListener('dashOnDrop', handler); element.addEventListener('dashPreDrop', preDropHandler); @@ -218,19 +240,19 @@ export namespace DragManager { dragData.draggedDocuments.map(async d => !dragData.isDocDecorationMove && !dragData.userDropAction && ScriptCast(d.onDragStart) ? addAudioTag(ScriptCast(d.onDragStart).script.run({ this: d }).result) - : docDragData.dropAction === 'embed' + : docDragData.dropAction === dropActionType.embed ? Doc.BestEmbedding(d) - : docDragData.dropAction === 'add' + : docDragData.dropAction === dropActionType.add ? d - : docDragData.dropAction === 'proto' + : docDragData.dropAction === dropActionType.proto ? d[DocData] - : docDragData.dropAction === 'copy' + : docDragData.dropAction === dropActionType.copy ? (await Doc.MakeClone(d)).clone : d ) ) ).filter(d => d); - !['same', 'proto'].includes(docDragData.dropAction as any) && + ![dropActionType.same, dropActionType.proto].includes(docDragData.dropAction as any) && docDragData.droppedDocuments // .filter(drop => !drop.dragOnlyWithinContainer || ['embed', 'copy'].includes(docDragData.dropAction as any)) .forEach((drop: Doc, i: number) => { @@ -504,7 +526,7 @@ export namespace DragManager { const moveHandler = (e: PointerEvent) => { e.preventDefault(); // required or dragging text menu link item ends up dragging the link button as native drag/drop if (dragData instanceof DocumentDragData) { - dragData.userDropAction = e.ctrlKey && e.altKey ? 'copy' : e.shiftKey ? 'move' : e.ctrlKey ? 'embed' : dragData.defaultDropAction; + dragData.userDropAction = e.ctrlKey && e.altKey ? dropActionType.copy : e.shiftKey ? dropActionType.move : e.ctrlKey ? dropActionType.embed : dragData.defaultDropAction; } if (['lm_tab', 'lm_title_wrap', 'lm_tabs', 'lm_header'].includes(typeof (e.target as any).className === 'string' ? (e.target as any)?.className : '') && dragData.draggedDocuments.length === 1) { if (!startWindowDragTimer) { @@ -530,7 +552,7 @@ export namespace DragManager { if (target && !Doc.UserDoc()._noAutoscroll && !options?.noAutoscroll && !dragData.draggedDocuments?.some((d: any) => d._freeform_noAutoPan)) { const autoScrollHandler = () => { target.dispatchEvent( - new CustomEvent<React.DragEvent>('dashDragAutoScroll', { + new CustomEvent<React.DragEvent>('dashDragMovePause', { bubbles: true, detail: { shiftKey: e.shiftKey, @@ -552,7 +574,7 @@ export namespace DragManager { screenY: e.screenY, detail: e.detail, view: e.view ? e.view : (new Window() as any), - nativeEvent: new DragEvent('dashDragAutoScroll'), + nativeEvent: new DragEvent('dashDragMovePause'), currentTarget: target, target: target, bubbles: true, @@ -566,7 +588,7 @@ export namespace DragManager { isPropagationStopped: () => ('not implemented for this event' ? false : false), persist: emptyFunction, timeStamp: e.timeStamp, - type: 'dashDragAutoScroll', + type: 'dashDragMovePause', }, }) ); diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index b6cb845a6..3be52597a 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -19,7 +19,7 @@ import { Docs } from '../documents/Documents'; import { CalendarManager } from '../util/CalendarManager'; import { CaptureManager } from '../util/CaptureManager'; import { DocumentManager } from '../util/DocumentManager'; -import { DragManager } from '../util/DragManager'; +import { DragManager, dropActionType } from '../util/DragManager'; import { GroupManager } from '../util/GroupManager'; import { HistoryUtil } from '../util/History'; import { Hypothesis } from '../util/HypothesisUtils'; @@ -623,7 +623,7 @@ export class MainView extends ObservableReactComponent<{}> { isContentActive={returnTrue} // headerBar is awlays contentActive which means its items are always documentActive ScreenToLocalTransform={this.headerBarScreenXf} childHideResizeHandles={true} - childDragAction="move" + childDragAction={dropActionType.move} dontRegisterView={true} hideResizeHandles={true} PanelWidth={this.headerBarDocWidth} @@ -905,7 +905,7 @@ export class MainView extends ObservableReactComponent<{}> { Document={Doc.MyDockedBtns} docViewPath={returnEmptyDocViewList} fieldKey="data" - dropAction="embed" + dropAction={dropActionType.embed} styleProvider={DefaultStyleProvider} select={emptyFunction} isAnyChildContentActive={returnFalse} diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx index 0f90818ef..8729ef549 100644 --- a/src/client/views/collections/CollectionMenu.tsx +++ b/src/client/views/collections/CollectionMenu.tsx @@ -11,7 +11,7 @@ import { RichTextField } from '../../../fields/RichTextField'; import { BoolCast, Cast, DocCast, NumCast, StrCast } from '../../../fields/Types'; import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue, setupMoveUpEvents, Utils } from '../../../Utils'; import { CollectionViewType, DocumentType } from '../../documents/DocumentTypes'; -import { DragManager } from '../../util/DragManager'; +import { DragManager, dropActionType } from '../../util/DragManager'; import { SelectionManager } from '../../util/SelectionManager'; import { SettingsManager } from '../../util/SettingsManager'; import { Transform } from '../../util/Transform'; @@ -91,7 +91,7 @@ export class CollectionMenu extends AntimodeMenu<CollectionMenuProps> { Document={selDoc} docViewPath={returnEmptyDocViewList} fieldKey="data" - dropAction="embed" + dropAction={dropActionType.embed} styleProvider={DefaultStyleProvider} select={emptyFunction} isContentActive={returnTrue} diff --git a/src/client/views/collections/CollectionPileView.tsx b/src/client/views/collections/CollectionPileView.tsx index d0df77cbe..7d7f0bb61 100644 --- a/src/client/views/collections/CollectionPileView.tsx +++ b/src/client/views/collections/CollectionPileView.tsx @@ -13,6 +13,7 @@ import { computePassLayout, computeStarburstLayout } from './collectionFreeForm' import { CollectionFreeFormView } from './collectionFreeForm/CollectionFreeFormView'; import './CollectionPileView.scss'; import { CollectionSubView } from './CollectionSubView'; +import { dropActionType } from '../../util/DragManager'; @observer export class CollectionPileView extends CollectionSubView() { @@ -72,7 +73,7 @@ export class CollectionPileView extends CollectionSubView() { // pile children never have their contents active, but will be document active whenever the entire pile is. childContentsActive={returnFalse} childDocumentsActive={this._props.isDocumentActive} - childDragAction="move" + childDragAction={dropActionType.move} childClickScript={this.toggleIcon} /> </div> diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 786301136..4d60cbefc 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -153,12 +153,18 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree return res; } - protected onInternalPreDrop = (e: Event, de: DragManager.DropEvent, dropAction: dropActionType) => { + protected onInternalPreDrop = (e: Event, de: DragManager.DropEvent, targetDropAction: dropActionType) => { const dragData = de.complete.docDragData; if (dragData) { - const sameTree = Doc.AreProtosEqual(dragData.treeViewDoc, this.Document) ? true : false; + const sourceDragAction = dragData.dropAction; + const sameTree = () => Doc.AreProtosEqual(dragData.treeViewDoc, this.Document); const isAlreadyInTree = () => sameTree || dragData.draggedDocuments.some(d => d.embedContainer === this.Document && this.childDocs.includes(d)); - dragData.dropAction = dropAction && !isAlreadyInTree() ? dropAction : sameTree && dragData.dropAction !== 'inSame' ? 'same' : dragData.dropAction; + dragData.dropAction = + targetDropAction && !isAlreadyInTree() // if dropped document is not in the tree + ? targetDropAction // then use the target's drop action if it's specified + : !sameTree() || sourceDragAction === dropActionType.inPlace // if doc from another tree, or a non inPlace source drag action is specified + ? sourceDragAction // use the source dragAction + : dropActionType.same; // otherwise use same tree semantics to move within tree e.stopPropagation(); } }; @@ -287,7 +293,7 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree @observable _renderCount = 1; @computed get treeViewElements() { TraceMobx(); - const dragAction = StrCast(this.Document.childDragAction) as dropActionType; + const dragAction = StrCast(this.Document.childDragAction) as any as dropActionType; const addDoc = (doc: Doc | Doc[], relativeTo?: Doc, before?: boolean) => this.addDoc(doc, relativeTo, before); const moveDoc = (d: Doc | Doc[], target: Doc | undefined, addDoc: (doc: Doc | Doc[]) => boolean) => this._props.moveDocument?.(d, target, addDoc) || false; if (this._renderCount < this.treeChildren.length) setTimeout(action(() => (this._renderCount = Math.min(this.treeChildren.length, this._renderCount + 20)))); @@ -473,7 +479,7 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree isAnnotationOverlayScrollable={true} childDocumentsActive={this._props.isContentActive} fieldKey={this._props.fieldKey + '_annotations'} - dropAction="move" + dropAction={dropActionType.move} select={emptyFunction} addDocument={this.addAnnotationDocument} removeDocument={this.remAnnotationDocument} diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index 85f7cf7fe..4f2d8b9c0 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -439,7 +439,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> { droppedDocuments: Doc[], before: boolean, inside: number | boolean, - dropAction: dropActionType, + dropAction: dropActionType | undefined, removeDocument: DragManager.RemoveFunction | undefined, moveDocument: DragManager.MoveFunction | undefined, forceAdd: boolean, @@ -1161,7 +1161,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> { const before = pt[1] < rect.top + rect.height / 2; const inside = this.treeView.fileSysMode && !this.Document.isFolder ? false : pt[0] > rect.left + rect.width * 0.33 || (!before && this.treeViewOpen && this.childDocs?.length ? true : false); - const docs = this.treeView.onTreeDrop(de, (docs: Doc[]) => this.dropDocuments(docs, before, inside, 'copy', undefined, undefined, false, false)); + this.treeView.onTreeDrop(de, (docs: Doc[]) => this.dropDocuments(docs, before, inside, dropActionType.copy, undefined, undefined, false, false)); }; render() { diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 50a9feff8..50b3dbd70 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -462,7 +462,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection const eles = this.childLayoutPairs.map(pair => pair.layout).filter(cd => (this.Document._freeform_useClusters ? NumCast(cd.layout_cluster) : NumCast(cd.group, -1)) === cluster); const clusterDocs = eles.map(ele => DocumentManager.Instance.getDocumentView(ele, this.DocumentView?.())!); const { left, top } = clusterDocs[0].getBounds || { left: 0, top: 0 }; - const de = new DragManager.DocumentDragData(eles, e.ctrlKey || e.altKey ? 'embed' : undefined); + const de = new DragManager.DocumentDragData(eles, e.ctrlKey || e.altKey ? dropActionType.embed : undefined); de.moveDocument = this._props.moveDocument; de.offset = this.screenToFreeformContentsXf.transformDirection(ptsParent.clientX - left, ptsParent.clientY - top); DragManager.StartDocumentDrag( diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index a417d777a..d0e59180d 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -635,8 +635,13 @@ export class MarqueeView extends ObservableReactComponent<SubCollectionViewProps } MarqueeRef: HTMLDivElement | null = null; + /** + * This is called for every drag movement when a document is dragged over this collection. + * If the document is dragged within 25 pixels of the edge of the collection and paused, this will + * auto scroll the collection so that it can be dragged farther (unless auto panning has been disabled) + */ @action - onDragAutoScroll = (e: CustomEvent<React.DragEvent>) => { + onDragMovePause = (e: CustomEvent<React.DragEvent>) => { if ((e as any).handlePan || this._props.isAnnotationOverlay) return; (e as any).handlePan = true; @@ -659,7 +664,7 @@ export class MarqueeView extends ObservableReactComponent<SubCollectionViewProps <div className="marqueeView" ref={r => { - r?.addEventListener('dashDragAutoScroll', this.onDragAutoScroll as any); + r?.addEventListener('dashDragMovePause', this.onDragMovePause as any); this.MarqueeRef = r; }} style={{ diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index 31b4a2dd4..eee3836d2 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -10,7 +10,7 @@ import { BoolCast, Cast, DocCast, NumCast, StrCast } from '../../../../fields/Ty import { emptyFunction, returnEmptyDoclist, returnEmptyString, returnFalse, returnIgnore, returnNever, returnTrue, setupMoveUpEvents, smoothScroll } from '../../../../Utils'; import { Docs, DocumentOptions, DocUtils, FInfo } from '../../../documents/Documents'; import { DocumentManager } from '../../../util/DocumentManager'; -import { DragManager } from '../../../util/DragManager'; +import { DragManager, dropActionType } from '../../../util/DragManager'; import { SelectionManager } from '../../../util/SelectionManager'; import { undoable, undoBatch } from '../../../util/UndoManager'; import { ContextMenu } from '../../ContextMenu'; @@ -981,7 +981,7 @@ class CollectionSchemaViewDoc extends ObservableReactComponent<CollectionSchemaV styleProvider={this.noOpacityStyleProvider} waitForDoubleClickToClick={returnNever} defaultDoubleClick={returnIgnore} - dragAction="move" + dragAction={dropActionType.move} onClickScriptDisable="always" focus={this._props.schema.focusDocument} childFilters={this._props.schema.childDocFilters} diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx index 001ad5ab6..46867665d 100644 --- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx +++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx @@ -10,7 +10,7 @@ import { Doc, DocListCast, Field } from '../../../../fields/Doc'; import { RichTextField } from '../../../../fields/RichTextField'; import { BoolCast, Cast, DateCast, DocCast, FieldValue, StrCast } from '../../../../fields/Types'; import { ImageField } from '../../../../fields/URLField'; -import { FInfo } from '../../../documents/Documents'; +import { FInfo, FInfoFieldType } from '../../../documents/Documents'; import { DocFocusOrOpen } from '../../../util/DocumentManager'; import { Transform } from '../../../util/Transform'; import { undoBatch, undoable } from '../../../util/UndoManager'; @@ -29,6 +29,7 @@ import { Popup, Size, Type } from 'browndash-components'; import { IconLookup, faCaretDown } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { SettingsManager } from '../../../util/SettingsManager'; +import { dropActionType } from '../../../util/DragManager'; export interface SchemaTableCellProps { Document: Doc; @@ -86,7 +87,7 @@ export class SchemaTableCell extends ObservableReactComponent<SchemaTableCellPro isSelected: returnFalse, setHeight: returnFalse, select: emptyFunction, - dragAction: 'move', + dragAction: dropActionType.move, renderDepth: 1, isContentActive: returnFalse, whenChildContentsActiveChanged: emptyFunction, @@ -149,7 +150,7 @@ export class SchemaTableCell extends ObservableReactComponent<SchemaTableCellPro if (cellValue instanceof DateField) return ColumnType.Date; if (cellValue instanceof RichTextField) return ColumnType.RTF; if (typeof cellValue === 'number') return ColumnType.Any; - if (typeof cellValue === 'string' && columnTypeStr !== 'enumeration') return ColumnType.Any; + if (typeof cellValue === 'string' && columnTypeStr !== FInfoFieldType.enumeration) return ColumnType.Any; if (typeof cellValue === 'boolean') return ColumnType.Boolean; if (columnTypeStr && columnTypeStr in FInfotoColType) { diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index d131f72d5..abb1aa59f 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -413,7 +413,7 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document if (!Utils.isClick(e.clientX, e.clientY, this._downX, this._downY, Date.now())) { this.cleanupPointerEvents(); this._longPressSelector && clearTimeout(this._longPressSelector); - this.startDragging(this._downX, this._downY, ((e.ctrlKey || e.altKey) && 'embed') || ((this.Document.dragAction || this._props.dragAction || undefined) as dropActionType)); + this.startDragging(this._downX, this._downY, ((e.ctrlKey || e.altKey) && dropActionType.embed) || ((this.Document.dragAction || this._props.dragAction || undefined) as dropActionType)); } }; diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx index b8f6575dd..918987034 100644 --- a/src/client/views/nodes/trails/PresBox.tsx +++ b/src/client/views/nodes/trails/PresBox.tsx @@ -36,6 +36,7 @@ import { FocusViewOptions, FieldView, FieldViewProps } from '../FieldView'; import { ScriptingBox } from '../ScriptingBox'; import './PresBox.scss'; import { PresEffect, PresEffectDirection, PresMovement, PresStatus } from './PresEnums'; +import { dropActionType } from '../../../util/DragManager'; export interface pinDataTypes { scrollable?: boolean; dataviz?: number[]; @@ -1074,7 +1075,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() { }; childLayoutTemplate = () => Docs.Create.PresElementBoxDocument(); - removeDocument = (doc: Doc) => Doc.RemoveDocFromList(this.Document, this.fieldKey, doc); + removeDocument = (doc: Doc | Doc[]) => !(doc instanceof Doc ? [doc] : doc).map(d => Doc.RemoveDocFromList(this.Document, this.fieldKey, d)).some(p => !p); getTransform = () => this.ScreenToLocalBoxXf().translate(-5, -65); // listBox padding-left and pres-box-cont minHeight panelHeight = () => this._props.PanelHeight() - 40; /** @@ -2607,7 +2608,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() { childIgnoreNativeSize={true} moveDocument={returnFalse} ignoreUnrendered={true} - childDragAction="move" + childDragAction={dropActionType.move} setContentViewBox={emptyFunction} //childLayoutFitWidth={returnTrue} childOpacity={returnOne} diff --git a/src/client/views/topbar/TopBar.tsx b/src/client/views/topbar/TopBar.tsx index 4155800b8..0952dda20 100644 --- a/src/client/views/topbar/TopBar.tsx +++ b/src/client/views/topbar/TopBar.tsx @@ -25,6 +25,7 @@ import { Colors } from '../global/globalEnums'; import { DocumentViewInternal, returnEmptyDocViewList } from '../nodes/DocumentView'; import { DefaultStyleProvider } from '../StyleProvider'; import './TopBar.scss'; +import { dropActionType } from '../../util/DragManager'; /** * ABOUT: This is the topbar in Dash, which included the current Dashboard as well as access to information on the user @@ -102,7 +103,7 @@ export class TopBar extends React.Component { Document={selDoc} docViewPath={returnEmptyDocViewList} fieldKey="data" - dropAction="embed" + dropAction={dropActionType.embed} styleProvider={DefaultStyleProvider} select={emptyFunction} isContentActive={returnTrue} diff --git a/src/fields/documentSchemas.ts b/src/fields/documentSchemas.ts index 8eeb52709..1cacfe30c 100644 --- a/src/fields/documentSchemas.ts +++ b/src/fields/documentSchemas.ts @@ -96,9 +96,9 @@ export const documentSchema = createSchema({ // drag drop properties _dragOnlyWithinContainer: 'boolean', // whether document can be dropped into a different collection dragFactory: Doc, // the document that serves as the "template" for the onDragStart script. ie, to drag out copies of the dragFactory document. - dropAction: 'string', // override specifying what should happen when something is dropped on this document (can be "embed", "copy", "move") - dragAction: 'string', // override specifying what should happen when this document s dragged (can be "embed", "copy", "move") - childDragAction: 'string', // specify the override for what should happen when the child of a collection is dragged from it and dropped (can be "embed" or "copy") + dropAction: 'string', // override specifying what should happen when something is dropped on this document (dropActionType) + dragAction: 'string', // override specifying what should happen when this document s dragged (dropActionType) + childDragAction: 'string', // specify the override for what should happen when the child of a collection is dragged from it and dropped (dropActionType) dropPropertiesToRemove: listSpec('string'), // properties that should be removed from the embed/copy/etc of this document when it is dropped }); |