aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbobzel <zzzman@gmail.com>2021-02-23 01:53:52 -0500
committerbobzel <zzzman@gmail.com>2021-02-23 01:53:52 -0500
commit7035e2e6bdcb3efbfa3a4eca887b41eba87e6d6e (patch)
tree1ac91247a1276e54c10f836ae826d4393b34315d
parentf22163e9e4118df3faf06afc28045b84615fba0d (diff)
fixed backspace to delete text items in treeViews. simplified UndoRunInTempBatch. fixed clicking on sort line for treeView to only recognize actual clicks. fixed stayInCollection with DocDecorations to not create a giant gray square. prevent server crash when db has bad data somehow.
-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;