aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/client/util/CurrentUserUtils.ts2
-rw-r--r--src/client/util/DragManager.ts2
-rw-r--r--src/client/util/UndoManager.ts11
-rw-r--r--src/client/views/DocumentDecorations.tsx2
-rw-r--r--src/client/views/GlobalKeyHandler.ts13
-rw-r--r--src/client/views/collections/CollectionView.tsx9
-rw-r--r--src/client/views/collections/TreeView.tsx52
-rw-r--r--src/client/views/collections/collectionFreeForm/MarqueeView.tsx3
-rw-r--r--src/server/websocket.ts2
9 files changed, 46 insertions, 50 deletions
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 288f75592..beced8c3c 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -558,7 +558,7 @@ export class CurrentUserUtils {
_width: 60,
_height: 60,
watchedDocuments,
- onClick: ScriptField.MakeScript(click, { scriptContext: "any" }), system: true
+ onClick: ScriptField.MakeScript(click, { scriptContext: "any" })
}));
const userDoc = menuBtns[menuBtns.length - 1];
userDoc.userDoc = doc;
diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index 7b4d43793..19f1f8d15 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -13,7 +13,7 @@ import * as globalCssVariables from "../views/globalCssVariables.scss";
import { UndoManager } from "./UndoManager";
import { SnappingManager } from "./SnappingManager";
-export type dropActionType = "alias" | "copy" | "move" | "same" | "none" | undefined; // undefined = move
+export type dropActionType = "alias" | "copy" | "move" | "same" | "none" | undefined; // undefined = move, "same" = move but don't call removeDropProperties
export function SetupDrag(
_reference: React.RefObject<HTMLElement>,
docFunc: () => Doc | Promise<Doc> | undefined,
diff --git a/src/client/util/UndoManager.ts b/src/client/util/UndoManager.ts
index 569ad8ab4..05fb9f378 100644
--- a/src/client/util/UndoManager.ts
+++ b/src/client/util/UndoManager.ts
@@ -148,12 +148,15 @@ export namespace UndoManager {
}
});
- export function ClearTempBatch() {
- tempEvents = undefined;
- }
export function RunInTempBatch<T>(fn: () => T) {
tempEvents = [];
- return runInAction(fn);
+ try {
+ const success = runInAction(fn);
+ if (!success) UndoManager.UndoTempBatch();
+ return success;
+ } finally {
+ tempEvents = undefined;
+ }
}
//TODO Make this return the return value
export function RunInBatch<T>(fn: () => T, batchName: string) {
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 7f1023a4a..2391a21e6 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -566,7 +566,7 @@ export class DocumentDecorations extends React.Component<{ boundsLeft: number, b
(collectionAcl === AclAdmin || collectionAcl === AclEdit || docAcl === AclAdmin);
});
const canOpen = SelectionManager.Views().some(docView => !docView.props.Document._stayInCollection);
- const closeIcon = !canDelete ? (null) : (
+ const closeIcon = !canDelete ? <div></div> : (
<Tooltip title={<div className="dash-tooltip">Close</div>} placement="top">
<div className="documentDecorations-closeButton" onClick={this.onCloseClick}>
<FontAwesomeIcon className="documentdecorations-times" icon={"times"} size="lg" />
diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts
index 3ebcda219..14c0a18a3 100644
--- a/src/client/views/GlobalKeyHandler.ts
+++ b/src/client/views/GlobalKeyHandler.ts
@@ -142,13 +142,14 @@ export class KeyManager {
break;
case "delete":
case "backspace":
- if (document.activeElement?.tagName === "INPUT" || document.activeElement?.tagName === "TEXTAREA") {
- return { stopPropagation: false, preventDefault: false };
+ if (document.activeElement?.tagName !== "INPUT" && document.activeElement?.tagName !== "TEXTAREA") {
+ const selected = SelectionManager.Views().slice();
+ UndoManager.RunInBatch(() => {
+ SelectionManager.DeselectAll();
+ selected.map(dv => !dv.props.Document._stayInCollection && dv.props.removeDocument?.(dv.props.Document));
+ }, "delete");
+ return { stopPropagation: true, preventDefault: true };
}
-
- const selected = SelectionManager.Views().slice();
- UndoManager.RunInBatch(() => selected.map(dv => !dv.props.Document._stayInCollection && dv.props.removeDocument?.(dv.props.Document)), "delete");
- SelectionManager.DeselectAll();
break;
case "arrowleft": UndoManager.RunInBatch(() => SelectionManager.Views().map(dv => dv.props.CollectionFreeFormDocumentView?.().nudge(-1, 0)), "nudge left"); break;
case "arrowright": UndoManager.RunInBatch(() => SelectionManager.Views().map(dv => dv.props.CollectionFreeFormDocumentView?.().nudge?.(1, 0)), "nudge right"); break;
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index 9ae469930..f305174f1 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -211,14 +211,7 @@ export class CollectionView extends Touchable<CollectionViewProps> {
}
const first = doc instanceof Doc ? doc : doc[0];
if (!first?._stayInCollection && addDocument !== returnFalse) {
- if (UndoManager.RunInTempBatch(() => this.removeDocument(doc))) {
- const added = addDocument(doc);
- if (!added) UndoManager.UndoTempBatch();
- else UndoManager.ClearTempBatch();
-
- return added;
- }
- UndoManager.ClearTempBatch();
+ return UndoManager.RunInTempBatch(() => this.removeDocument(doc) && addDocument(doc));
}
return false;
}
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index aed6302ad..00e9456a1 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -39,14 +39,14 @@ export interface TreeViewProps {
containingCollection: Doc;
prevSibling?: Doc;
renderDepth: number;
- removeDoc: ((doc: Doc | Doc[]) => boolean) | undefined;
- moveDocument: DragManager.MoveFunction;
dropAction: dropActionType;
addDocTab: (doc: Doc, where: string) => boolean;
pinToPres: (document: Doc) => void;
panelWidth: () => number;
panelHeight: () => number;
addDocument: (doc: Doc | Doc[], relativeTo?: Doc, before?: boolean) => boolean;
+ removeDoc: ((doc: Doc | Doc[]) => boolean) | undefined;
+ moveDocument: DragManager.MoveFunction;
indentDocument?: (editTitle: boolean) => void;
outdentDocument?: (editTitle: boolean) => void;
ScreenToLocalTransform: () => Transform;
@@ -263,20 +263,15 @@ export class TreeView extends React.Component<TreeViewProps> {
e.stopPropagation();
if (docDragData.draggedDocuments[0] === this.doc) return true;
const parentAddDoc = (doc: Doc | Doc[]) => this.props.addDocument(doc, undefined, before);
- let addDoc = parentAddDoc;
- if (inside) {
- const localAdd = (doc: Doc) => {
- const added = Doc.AddDocToList(this.dataDoc, this.fieldKey, doc);
- added && (doc.context = this.doc.context);
- return added;
- };
- addDoc = (doc: Doc | Doc[]) => (doc instanceof Doc ? [doc] : doc).reduce(
- (flg: boolean, doc) => flg && localAdd(doc), true) || parentAddDoc(doc);
- }
+ const canAdd = !StrCast((inside ? this.props.document : this.props.containingCollection)?.freezeChildren).includes("add") || docDragData.treeViewDoc === this.props.treeView.props.Document;
+ const localAdd = (doc: Doc) => Doc.AddDocToList(this.dataDoc, this.fieldKey, doc) && ((doc.context = this.doc.context) || true) ? true : false;
+ const addDoc = !inside ? parentAddDoc :
+ (doc: Doc | Doc[]) => (doc instanceof Doc ? [doc] : doc).reduce((flg, doc) => flg && localAdd(doc), true as boolean);
const move = (!docDragData.dropAction || docDragData.dropAction === "move" || docDragData.dropAction === "same") && docDragData.moveDocument;
- return docDragData.droppedDocuments.reduce((added, d) => (move ? docDragData.moveDocument?.(d, undefined, addDoc) : addDoc(d)) || added, false);
+ if (canAdd) {
+ UndoManager.RunInTempBatch(() => docDragData.droppedDocuments.reduce((added, d) => (move ? move(d, undefined, addDoc) : addDoc(d)) || added, false));
+ }
}
- return false;
}
refTransform = (ref: HTMLDivElement | undefined | null) => {
@@ -401,16 +396,19 @@ export class TreeView extends React.Component<TreeViewProps> {
const addDoc = (doc: Doc | Doc[], addBefore?: Doc, before?: boolean) => (doc instanceof Doc ? [doc] : doc).reduce((flg, doc) => flg && localAdd(doc, addBefore, before), true);
const docs = expandKey === "links" ? this.childLinks : expandKey === "annotations" ? this.childAnnos : this.childDocs;
const sortKey = `${this.fieldKey}-sortCriteria`;
- return <ul key={expandKey + "more"} className={this.doc.treeViewHideTitle ? "no-indent" : ""} onClick={(e) => {
- if (this.props.active()) {
- !this.outlineMode && (this.doc[sortKey] =
- (this.doc[sortKey] === "ascending" ? "descending" :
- (this.doc[sortKey] === "descending" ? "zorder" :
- (this.doc[sortKey] === "zorder" ? undefined :
- "ascending"))));
- e.stopPropagation();
- }
- }}>
+ let downX = 0, downY = 0;
+ return <ul key={expandKey + "more"} className={this.doc.treeViewHideTitle ? "no-indent" : ""}
+ onPointerDown={e => { downX = e.clientX; downY = e.clientY; }}
+ onClick={(e) => {
+ if (this.props.active() && Math.abs(e.clientX - downX) < 3 && Math.abs(e.clientY - downY) < 3) {
+ !this.outlineMode && (this.doc[sortKey] =
+ (this.doc[sortKey] === "ascending" ? "descending" :
+ (this.doc[sortKey] === "descending" ? "zorder" :
+ (this.doc[sortKey] === "zorder" ? undefined :
+ "ascending"))));
+ e.stopPropagation();
+ }
+ }}>
{!docs ? (null) :
TreeView.GetChildElements(docs, this.props.treeView, this.layoutDoc,
this.dataDoc, expandKey, this.props.containingCollection, this.props.prevSibling, addDoc, remDoc, this.move,
@@ -571,7 +569,7 @@ export class TreeView extends React.Component<TreeViewProps> {
: <DocumentView key="title"
ref={action((r: any) => {
this._docRef = r ? r : undefined;
- if (this._docRef && TreeView._editTitleOnLoad?.id === this.props.document[Id] && TreeView._editTitleOnLoad.parent == this.props.parentTreeView) {
+ if (this._docRef && TreeView._editTitleOnLoad?.id === this.props.document[Id] && TreeView._editTitleOnLoad.parent === this.props.parentTreeView) {
this._docRef.select(false);
this.setEditTitle(this._docRef);
TreeView._editTitleOnLoad = undefined;
@@ -772,7 +770,7 @@ export class TreeView extends React.Component<TreeViewProps> {
parentCollectionDoc: Doc | undefined,
parentPrevSibling: Doc | undefined,
add: (doc: Doc | Doc[], relativeTo?: Doc, before?: boolean) => boolean,
- remove: ((doc: Doc | Doc[]) => boolean),
+ remove: undefined | ((doc: Doc | Doc[]) => boolean),
move: DragManager.MoveFunction,
dropAction: dropActionType,
addDocTab: (doc: Doc, where: string) => boolean,
@@ -818,7 +816,7 @@ export class TreeView extends React.Component<TreeViewProps> {
newParent.treeViewOpen = true;
child.context = treeView.Document;
}
- }
+ };
const indent = i === 0 ? undefined : (editTitle: boolean) => dentDoc(editTitle, docs[i - 1], undefined, treeViewRefs.get(docs[i - 1]));
const outdent = parentCollectionDoc?._viewType !== CollectionViewType.Tree ? undefined : ((editTitle: boolean) => dentDoc(editTitle, parentCollectionDoc, parentPrevSibling, parentTreeView instanceof TreeView ? parentTreeView.props.parentTreeView : undefined));
const addDocument = (doc: Doc | Doc[], relativeTo?: Doc, before?: boolean) => add(doc, relativeTo ?? docs[i], before !== undefined ? before : false);
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index 36d14056b..4008a20b3 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -28,6 +28,7 @@ import { MarqueeOptionsMenu } from "./MarqueeOptionsMenu";
import "./MarqueeView.scss";
import React = require("react");
import { StyleLayers } from "../../StyleProvider";
+import { TreeView } from "../TreeView";
interface MarqueeViewProps {
getContainerTransform: () => Transform;
@@ -161,8 +162,8 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
slide.x = x;
slide.y = y;
FormattedTextBox.SelectOnLoad = slide[Id];
+ TreeView._editTitleOnLoad = { id: slide[Id], parent: undefined };
this.props.addDocument?.(slide);
- //setTimeout(() => SelectionManager.SelectDoc(DocumentManager.Instance.getDocumentView(slide)!, false));
e.stopPropagation();
} else if (!e.ctrlKey && !e.metaKey && SelectionManager.Views().length < 2) {
FormattedTextBox.SelectOnLoadChar = FormattedTextBox.DefaultLayout && !this.props.childLayoutString ? e.key : "";
diff --git a/src/server/websocket.ts b/src/server/websocket.ts
index 6850f0601..7e3c4da82 100644
--- a/src/server/websocket.ts
+++ b/src/server/websocket.ts
@@ -299,7 +299,7 @@ export namespace WebSocket {
diff.diff.$set = diff.diff.$remFromSet; delete diff.diff.$remFromSet;
const updatefield = Array.from(Object.keys(diff.diff.$set))[0];
const remListItems = diff.diff.$set[updatefield].fields;
- const curList = (curListItems as any)?.fields?.[updatefield.replace("fields.", "")]?.fields || [];
+ const curList = (curListItems as any)?.fields?.[updatefield.replace("fields.", "")]?.fields.filter((f: any) => f !== null) || [];
diff.diff.$set[updatefield].fields = curList?.filter((curItem: any) => !remListItems.some((remItem: any) => remItem.fieldId ? remItem.fieldId === curItem.fieldId : remItem.heading ? remItem.heading === curItem.heading : remItem === curItem));
const sendBack = diff.diff.length !== diff.diff.$set[updatefield].fields.length;
delete diff.diff.length;